1<?php
2
3function get_zend_debug_type($v) {
4    if ($v === true) {
5        return 'true';
6    }
7    if ($v === false) {
8        return 'false';
9    }
10    if (is_resource($v)) {
11        return 'resource';
12    }
13    return get_debug_type($v);
14}
15function zend_test_var_export($value) {
16    if ($value === PHP_INT_MIN) {
17        return "PHP_INT_MIN";
18    }
19    if ($value === PHP_INT_MAX) {
20        return "PHP_INT_MAX";
21    }
22    if (is_array($value)) {
23        return "[]";
24    }
25    if (is_resource($value)) {
26        return "STDERR";
27    }
28    if ($value instanceof stdClass) {
29        return "new stdClass()";
30    }
31    if ($value instanceof B) {
32        return "new B()";
33    }
34    if ($value instanceof A) {
35        return "new A()";
36    }
37    if ($value instanceof ArrayObject) {
38        return "new ArrayObject()";
39    }
40    return var_export($value, true);
41}
42
43function exportProp(object $o, string $p) {
44    $rp = new ReflectionProperty($o, $p);
45
46    echo ', ', $p, ': ';
47    if ($rp->isInitialized($o)) {
48        if ($p === 'readType') {
49            echo match($o->$p) {
50                0 => 'BP_VAR_R',
51                1 => 'BP_VAR_W',
52                2 => 'BP_VAR_RW',
53                3 => 'BP_VAR_IS',
54                4 => 'BP_VAR_FUNC_ARG',
55                5 => 'BP_VAR_UNSET',
56            };
57        } else {
58            echo zend_test_var_export($o->$p);
59        }
60    } else {
61        echo 'uninitialized';
62    }
63}
64
65function exportObject(object $o) {
66    echo $o::class;
67    foreach (get_class_vars($o::class) as $p => $v) {
68        exportProp($o, $p);
69    }
70    echo "\n";
71}
72
73/* Taken from run-tests.php */
74function expectf_to_regex(string $wanted): string
75{
76    $wanted_re = preg_quote($wanted);
77    return strtr($wanted_re, [
78        '%e' => preg_quote(DIRECTORY_SEPARATOR, '/'),
79        '%s' => '[^\r\n]+',
80        '%S' => '[^\r\n]*',
81        '%a' => '.+',
82        '%A' => '.*',
83        '%w' => '\s*',
84        '%i' => '[+-]?\d+',
85        '%d' => '\d+',
86        '%x' => '[0-9a-fA-F]+',
87        '%f' => '[+-]?(?:\d+|(?=\.\d))(?:\.\d+)?(?:[Ee][+-]?\d+)?',
88        '%F' => '([+-]?(?:\d+|(?=\.\d))(?:\.\d+)?(?:[Ee][+-]?\d+)?)|(NAN)|(INF)',
89        '%c' => '.',
90        '%0' => '\x00',
91    ]);
92}
93
94class A implements ArrayAccess {
95    public function offsetSet($offset, $value): void {
96        var_dump(__METHOD__);
97        var_dump($offset);
98        var_dump($value);
99    }
100    public function offsetGet($offset): mixed {
101        var_dump(__METHOD__);
102        var_dump($offset);
103        return 5;
104    }
105    public function offsetUnset($offset): void {
106        var_dump(__METHOD__);
107        var_dump($offset);
108    }
109    public function offsetExists($offset): bool {
110        var_dump(__METHOD__);
111        var_dump($offset);
112        return true;
113    }
114}
115
116class B extends ArrayObject {
117    public function offsetSet($offset, $value): void {
118        var_dump(__METHOD__);
119        var_dump($offset);
120        var_dump($value);
121    }
122    public function offsetGet($offset): mixed {
123        var_dump(__METHOD__);
124        var_dump($offset);
125        return 5;
126    }
127    public function offsetUnset($offset): void {
128        var_dump(__METHOD__);
129        var_dump($offset);
130    }
131    public function offsetExists($offset): bool {
132        var_dump(__METHOD__);
133        var_dump($offset);
134        return true;
135    }
136    public function append(mixed $value) : void{
137        var_dump(__METHOD__);
138        var_dump($value);
139    }
140}
141
142$containers = [
143    null,
144    false,
145    true,
146    4,
147    5.5,
148    '10',
149    '25.5',
150    'string',
151    [],
152    STDERR,
153    new stdClass(),
154    new ArrayObject(),
155    new A(),
156    new B(),
157];
158
159$offsets = [
160    null,
161    false,
162    true,
163    4,
164    5.5,
165    6.0,
166    -12,
167    -13.5,
168    -14.0,
169    //PHP_INT_MAX,
170    //PHP_INT_MIN,
171    PHP_INT_MAX * 2,
172    PHP_INT_MIN * 2,
173    INF,
174    -INF,
175    NAN,
176    'string',
177    '7',
178    '8.5',
179    '9.0',
180    '2e3',
181    '20a',
182    '  21',
183    '22  ',
184    //"9179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368",
185    //"-9179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368",
186    '0x14',
187    '-15',
188    '-16.5',
189    '-17.0',
190    (string) PHP_INT_MAX * 2,
191    (string) PHP_INT_MIN * 2,
192    [],
193    STDERR,
194    new stdClass(),
195    new ArrayObject(),
196    new A(),
197    new B(),
198];
199
200$failures = [];
201$failuresNb = 0;
202$testCasesTotal = 0;
203
204$var_dim_filename = __DIR__ . DIRECTORY_SEPARATOR . 'test_variable_offsets.inc';
205