Rev 42 | Rev 46 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 42 | Rev 43 | ||
---|---|---|---|
Line 2... | Line 2... | ||
2 | 2 | ||
3 | // TODO: show full signature of each element? |
3 | // TODO: show full signature of each element? |
4 | 4 | ||
5 | error_reporting(0); |
5 | error_reporting(0); |
6 | 6 | ||
7 | define('ICON_TYPE_FUNCTION', 'FUN'); |
- | |
8 | define('ICON_TYPE_CONSTRUCTOR', 'CST'); |
- | |
9 | define('ICON_TYPE_DESTRUCTOR', 'DST'); |
- | |
10 | define('ICON_TYPE_MAGICMETHOD', 'MAG'); |
- | |
11 | define('ICON_TYPE_CLASS', 'CLS'); |
- | |
12 | define('ICON_TYPE_TRAIT', 'TRA'); |
- | |
13 | define('ICON_TYPE_INTERFACE', 'INT'); |
- | |
14 | define('ICON_TYPE_VAR', 'VAR'); |
- | |
15 | define('ICON_TYPE_CONST', 'CON'); |
- | |
16 | define('ICON_TYPE_TODO', 'TDO'); |
7 | require_once __DIR__ . '/codeexplorer_api.inc.php'; |
17 | define('ICON_TYPE_ERROR', 'ERR'); |
- | |
18 | 8 | ||
- | 9 | define('ICON_TYPE_FUNCTION', 1); |
|
- | 10 | define('ICON_TYPE_CONSTRUCTOR', 2); |
|
- | 11 | define('ICON_TYPE_DESTRUCTOR', 3); |
|
- | 12 | define('ICON_TYPE_MAGICMETHOD', 4); |
|
- | 13 | define('ICON_TYPE_CLASS', 5); |
|
- | 14 | define('ICON_TYPE_TRAIT', 6); |
|
- | 15 | define('ICON_TYPE_INTERFACE', 7); |
|
- | 16 | define('ICON_TYPE_VAR', 8); |
|
- | 17 | define('ICON_TYPE_CONST', 9); |
|
- | 18 | define('ICON_TYPE_TODO', 10); |
|
- | 19 | define('ICON_TYPE_ERROR', 11); |
|
- | 20 | ||
- | 21 | class MyFastPHPIcon extends FastPHPIcon { |
|
- | 22 | ||
- | 23 | public function imageIndex() { |
|
- | 24 | if (($this->getType() == ICON_TYPE_CLASS) && (!$this->isAbstract())) return 0; // class |
|
- | 25 | else if (($this->getType() == ICON_TYPE_CLASS) && ( $this->isAbstract())) return 1; // abstract class |
|
- | 26 | else if (($this->getType() == ICON_TYPE_INTERFACE) ) return 2; // interface |
|
- | 27 | else if (($this->getType() == ICON_TYPE_TRAIT) ) return 3; // trait |
|
- | 28 | else if (($this->getType() == ICON_TYPE_CONST) && ($this->isPrivate()) ) return 4; // private const |
|
- | 29 | else if (($this->getType() == ICON_TYPE_VAR) && ($this->isPrivate()) ) return 5; // private var |
|
- | 30 | else if (($this->isMethod()) && ($this->isPrivate()) && (!$this->isAbstract())) return 6; // private function |
|
- | 31 | else if (($this->isMethod()) && ($this->isPrivate()) && ( $this->isAbstract())) return 7; // private abstract function |
|
- | 32 | else if (($this->getType() == ICON_TYPE_CONST) && ($this->isProtected()) ) return 8; // protected const |
|
- | 33 | else if (($this->getType() == ICON_TYPE_VAR) && ($this->isProtected()) ) return 9; // protected var |
|
- | 34 | else if (($this->isMethod()) && ($this->isProtected()) && (!$this->isAbstract())) return 10; // protected function |
|
- | 35 | else if (($this->isMethod()) && ($this->isProtected()) && ( $this->isAbstract())) return 11; // protected abstract function |
|
- | 36 | else if (($this->getType() == ICON_TYPE_CONST) && ($this->isPublic()) ) return 12; // public const |
|
- | 37 | else if (($this->getType() == ICON_TYPE_VAR) && ($this->isPublic()) ) return 13; // public var |
|
- | 38 | else if (($this->isMethod()) && ($this->isPublic()) && (!$this->isAbstract())) return 14; // public function |
|
- | 39 | else if (($this->isMethod()) && ($this->isPublic()) && ( $this->isAbstract())) return 15; // public abstract function |
|
- | 40 | else if (($this->getType() == ICON_TYPE_TODO) ) return 16; // ToDo comment |
|
- | 41 | else return -1; |
|
- | 42 | } |
|
- | 43 | ||
19 | while (true) { |
44 | public function isMethod() { |
20 | $code = FastNodeReader::readCodeFromEditor(); |
45 | return (($this->getType() == ICON_TYPE_FUNCTION) || |
- | 46 | ($this->getType() == ICON_TYPE_CONSTRUCTOR) || |
|
- | 47 | ($this->getType() == ICON_TYPE_DESTRUCTOR) || |
|
- | 48 | ($this->getType() == ICON_TYPE_MAGICMETHOD)); |
|
- | 49 | } |
|
- | 50 | ||
- | 51 | } |
|
21 | 52 | ||
- | 53 | class MyFastPHPCodeExplorer { |
|
- | 54 | ||
- | 55 | public function handle($code) { |
|
22 | $x = token_get_all($code); |
56 | $token = token_get_all($code); |
23 | $wait_function = false; |
57 | $wait_function = false; |
- | 58 | $wait_const = false; |
|
24 | $wait_class = false; |
59 | $wait_class = false; |
25 | $wait_trait = false; |
60 | $wait_trait = false; |
- | 61 | $icon = new MyFastPHPIcon(); |
|
26 | $wait_interface = false; |
62 | $wait_interface = false; |
27 | $wait_abstract_func_list_end = false; |
63 | $wait_abstract_func_list_end = false; |
28 | $levelAry = array(); |
64 | $levelAry = array(); |
29 | $icon = new FastPHPIcon(); |
- | |
30 | $dep = 0; |
65 | $dep = 0; |
31 | $insideFuncAry = array(); |
66 | $insideFuncAry = array(); |
32 | 67 | ||
33 | echo FastNodeWriter::outputHeader(); |
- | |
34 | - | ||
35 | if (!$x) { |
68 | if (!$token) { |
36 | $icon->setType(ICON_TYPE_ERROR); |
69 | $icon->setType(ICON_TYPE_ERROR); |
37 | echo FastNodeWriter::outputLeafNode($icon, 1, 'SYNTAX ERROR'); |
70 | FastPHPWriter::outputLeafNode($icon, 0, 'SYNTAX ERROR'); |
38 | } |
71 | } |
39 | 72 | ||
40 | foreach ($x as $n => $data) { |
73 | foreach ($token as $data) { |
41 | if ($data == '{') $dep++; |
74 | if ($data == '{') $dep++; |
42 | if ($data == '}') { |
75 | if ($data == '}') { |
43 | $dep--; |
76 | $dep--; |
44 | if ((count($levelAry) > 0) && (array_peek($levelAry) == $dep)) { |
77 | if ((count($levelAry) > 0) && (self::array_peek($levelAry) == $dep)) { |
45 | array_pop($levelAry); |
78 | array_pop($levelAry); |
46 | echo FastNodeWriter::outputDecreaseLevel(); |
79 | FastPHPWriter::outputDecreaseLevel(); |
47 | } |
80 | } |
48 | if ((count($insideFuncAry) > 0) && (array_peek($insideFuncAry) == $dep)) { |
81 | if ((count($insideFuncAry) > 0) && (self::array_peek($insideFuncAry) == $dep)) { |
49 | array_pop($insideFuncAry); |
82 | array_pop($insideFuncAry); |
50 | } |
83 | } |
51 | } |
84 | } |
52 | 85 | ||
53 | $token = (!is_array($data)) ? null : $data[0]; |
86 | $token = (!is_array($data)) ? null : $data[0]; |
Line 71... | Line 104... | ||
71 | } else if (substr($value, 0, 2) == '__') { |
104 | } else if (substr($value, 0, 2) == '__') { |
72 | $icon->setType(ICON_TYPE_MAGICMETHOD); |
105 | $icon->setType(ICON_TYPE_MAGICMETHOD); |
73 | } else { |
106 | } else { |
74 | $icon->setType(ICON_TYPE_FUNCTION); |
107 | $icon->setType(ICON_TYPE_FUNCTION); |
75 | } |
108 | } |
76 | echo FastNodeWriter::outputLeafNode($icon, $line, $desc); |
109 | FastPHPWriter::outputLeafNode($icon, $line, $desc); |
77 | $icon->reset(); |
110 | $icon->reset(); |
78 | } |
111 | } |
79 | 112 | ||
80 | if ($wait_class && ($token == T_STRING)) { |
113 | if ($wait_class && ($token == T_STRING)) { |
81 | if ($icon->isAbstract()) { |
114 | if ($icon->isAbstract()) { |
Line 85... | Line 118... | ||
85 | } |
118 | } |
86 | $wait_class = false; |
119 | $wait_class = false; |
87 | $levelAry[] = $dep; |
120 | $levelAry[] = $dep; |
88 | 121 | ||
89 | $icon->setType(ICON_TYPE_CLASS); |
122 | $icon->setType(ICON_TYPE_CLASS); |
90 | echo FastNodeWriter::outputLeafNode($icon, $line, $desc); |
123 | FastPHPWriter::outputLeafNode($icon, $line, $desc); |
91 | $icon->reset(); |
124 | $icon->reset(); |
92 | 125 | ||
93 | echo FastNodeWriter::outputIncreaseLevel(); |
126 | FastPHPWriter::outputIncreaseLevel(); |
94 | } |
127 | } |
95 | 128 | ||
96 | if ($wait_trait && ($token == T_STRING)) { |
129 | if ($wait_trait && ($token == T_STRING)) { |
97 | $desc = "Trait $value\n"; |
130 | $desc = "Trait $value\n"; |
98 | $wait_trait = false; |
131 | $wait_trait = false; |
99 | $levelAry[] = $dep; |
132 | $levelAry[] = $dep; |
100 | 133 | ||
101 | $icon->setType(ICON_TYPE_TRAIT); |
134 | $icon->setType(ICON_TYPE_TRAIT); |
102 | echo FastNodeWriter::outputLeafNode($icon, $line, $desc); |
135 | FastPHPWriter::outputLeafNode($icon, $line, $desc); |
103 | $icon->reset(); |
136 | $icon->reset(); |
104 | 137 | ||
105 | echo FastNodeWriter::outputIncreaseLevel(); |
138 | FastPHPWriter::outputIncreaseLevel(); |
106 | } |
139 | } |
107 | 140 | ||
108 | if ($wait_interface && ($token == T_STRING)) { |
141 | if ($wait_interface && ($token == T_STRING)) { |
109 | $desc = "Interface $value\n"; |
142 | $desc = "Interface $value\n"; |
110 | $wait_interface = false; |
143 | $wait_interface = false; |
111 | $levelAry[] = $dep; |
144 | $levelAry[] = $dep; |
112 | 145 | ||
113 | $icon->setType(ICON_TYPE_INTERFACE); |
146 | $icon->setType(ICON_TYPE_INTERFACE); |
114 | echo FastNodeWriter::outputLeafNode($icon, $line, $desc); |
147 | FastPHPWriter::outputLeafNode($icon, $line, $desc); |
115 | $icon->reset(); |
148 | $icon->reset(); |
116 | 149 | ||
117 | echo FastNodeWriter::outputIncreaseLevel(); |
150 | FastPHPWriter::outputIncreaseLevel(); |
118 | } |
151 | } |
119 | 152 | ||
120 | if ($wait_const && ($token == T_STRING)) { |
153 | if ($wait_const && ($token == T_STRING)) { |
121 | $desc = "const $value\n"; |
154 | $desc = "const $value\n"; |
122 | $wait_const = false; |
155 | $wait_const = false; |
123 | 156 | ||
124 | $icon->setType(ICON_TYPE_CONST); |
157 | $icon->setType(ICON_TYPE_CONST); |
125 | echo FastNodeWriter::outputLeafNode($icon, $line, $desc); |
158 | FastPHPWriter::outputLeafNode($icon, $line, $desc); |
126 | $icon->reset(); |
159 | $icon->reset(); |
127 | } |
160 | } |
128 | 161 | ||
129 | if ((!$wait_abstract_func_list_end) && (count($levelAry) > 0) && (count($insideFuncAry) == 0) && ($token == T_VARIABLE)) { |
162 | if ((!$wait_abstract_func_list_end) && (count($levelAry) > 0) && (count($insideFuncAry) == 0) && ($token == T_VARIABLE)) { |
130 | $desc = "$value\n"; |
163 | $desc = "$value\n"; |
131 | 164 | ||
132 | $icon->setType(ICON_TYPE_VAR); |
165 | $icon->setType(ICON_TYPE_VAR); |
133 | echo FastNodeWriter::outputLeafNode($icon, $line, $desc); |
166 | FastPHPWriter::outputLeafNode($icon, $line, $desc); |
134 | $icon->reset(); |
167 | $icon->reset(); |
135 | } |
168 | } |
136 | 169 | ||
137 | if ($token == T_PRIVATE) $icon->setPrivate(); |
170 | if ($token == T_PRIVATE) $icon->setPrivate(); |
138 | if ($token == T_PROTECTED) $icon->setProtected(); |
171 | if ($token == T_PROTECTED) $icon->setProtected(); |
Line 164... | Line 197... | ||
164 | 197 | ||
165 | if ($token == T_CONST) { |
198 | if ($token == T_CONST) { |
166 | $wait_const = true; |
199 | $wait_const = true; |
167 | } |
200 | } |
168 | 201 | ||
169 | if (($token == T_COMMENT) && _isToDoDescription($value)) { |
202 | if (($token == T_COMMENT) && self::isToDoDescription($value)) { |
170 | // Because a TO-DO-entry can stand everywhere (e.g. between a "private" and a "function") |
203 | // Because a TO-DO-entry can stand everywhere (e.g. between a "private" and a "function") |
171 | // we shall not alter the $icon instance |
204 | // we shall not alter the $icon instance |
172 | $todoIcon = clone $icon; |
205 | $todoIcon = clone $icon; |
173 | $todoIcon->setType(ICON_TYPE_TODO); |
206 | $todoIcon->setType(ICON_TYPE_TODO); |
- | 207 | unset($todoIcon); |
|
174 | echo FastNodeWriter::outputLeafNode($todoIcon, $line, strip_comment($value)); |
208 | FastPHPWriter::outputLeafNode($todoIcon, $line, self::stripComment($value)); |
175 | } |
209 | } |
176 | } |
210 | } |
177 | - | ||
178 | echo FastNodeWriter::outputExit(); |
- | |
179 | - | ||
180 | echo FastNodeWriter::signalOutputEnd(); |
- | |
181 | - | ||
182 | sleep(1); |
- | |
183 | } |
211 | } |
184 | 212 | ||
185 | function _isToDoDescription($comment) { |
213 | private static function isToDoDescription($comment) { |
186 | return ((stripos($value, 'TODO') !== false) || |
214 | return ((stripos($value, 'TODO') !== false) || |
187 | (stripos($value, 'BUGBUG') !== false) || |
215 | (stripos($value, 'BUGBUG') !== false) || |
188 | (stripos($value, 'FIXME') !== false) || |
216 | (stripos($value, 'FIXME') !== false) || |
189 | (stripos($value, 'XXX') !== false)); |
217 | (stripos($value, 'XXX') !== false)); |
190 | } |
218 | } |
191 | 219 | ||
192 | function _iconCodeToIndex(/* FastPHPIcon */ $icon) { |
- | |
193 | if (($icon->getType() == ICON_TYPE_CLASS) && (!$icon->isAbstract())) return 0; // class |
- | |
194 | else if (($icon->getType() == ICON_TYPE_CLASS) && ( $icon->isAbstract())) return 1; // abstract class |
- | |
195 | else if (($icon->getType() == ICON_TYPE_INTERFACE) ) return 2; // interface |
- | |
196 | else if (($icon->getType() == ICON_TYPE_TRAIT) ) return 3; // trait |
- | |
197 | else if (($icon->getType() == ICON_TYPE_CONST) && ($icon->isPrivate()) ) return 4; // private const |
- | |
198 | else if (($icon->getType() == ICON_TYPE_VAR) && ($icon->isPrivate()) ) return 5; // private var |
- | |
199 | else if (($icon->isMethod()) && ($icon->isPrivate()) && (!$icon->isAbstract())) return 6; // private function |
- | |
200 | else if (($icon->isMethod()) && ($icon->isPrivate()) && ( $icon->isAbstract())) return 7; // private abstract function |
- | |
201 | else if (($icon->getType() == ICON_TYPE_CONST) && ($icon->isProtected()) ) return 8; // protected const |
- | |
202 | else if (($icon->getType() == ICON_TYPE_VAR) && ($icon->isProtected()) ) return 9; // protected var |
- | |
203 | else if (($icon->isMethod()) && ($icon->isProtected()) && (!$icon->isAbstract())) return 10; // protected function |
- | |
204 | else if (($icon->isMethod()) && ($icon->isProtected()) && ( $icon->isAbstract())) return 11; // protected abstract function |
- | |
205 | else if (($icon->getType() == ICON_TYPE_CONST) && ($icon->isPublic()) ) return 12; // public const |
- | |
206 | else if (($icon->getType() == ICON_TYPE_VAR) && ($icon->isPublic()) ) return 13; // public var |
- | |
207 | else if (($icon->isMethod()) && ($icon->isPublic()) && (!$icon->isAbstract())) return 14; // public function |
- | |
208 | else if (($icon->isMethod()) && ($icon->isPublic()) && ( $icon->isAbstract())) return 15; // public abstract function |
- | |
209 | else if (($icon->getType() == ICON_TYPE_TODO) ) return 16; // ToDo comment |
- | |
210 | else return -1; |
- | |
211 | } |
- | |
212 | - | ||
213 | class FastPHPIcon { |
- | |
214 | private $type; // ICON_TYPE_* |
- | |
215 | private $visibility; // 1=private, 2=protected, 3=public(default) |
- | |
216 | private $abstractFinal; // 'A', 'F', ''(default) |
- | |
217 | private $static; // true, false(default) |
- | |
218 | - | ||
219 | public function setType($type) { |
- | |
220 | $this->type = $type; |
- | |
221 | } |
- | |
222 | public function getType() { |
- | |
223 | return $this->type; |
- | |
224 | } |
- | |
225 | - | ||
226 | public function setAbstract() { |
- | |
227 | $this->abstractFinal = 'A'; |
- | |
228 | } |
- | |
229 | public function isAbstract() { |
- | |
230 | return $this->abstractFinal == 'A'; |
- | |
231 | } |
- | |
232 | - | ||
233 | public function setFinal() { |
- | |
234 | $this->abstractFinal = 'F'; |
- | |
235 | } |
- | |
236 | public function isFinal() { |
- | |
237 | return $this->abstractFinal == 'F'; |
- | |
238 | } |
- | |
239 | - | ||
240 | public function setStatic() { |
- | |
241 | $this->static = true; |
- | |
242 | } |
- | |
243 | public function isStatic() { |
- | |
244 | return $this->static; |
- | |
245 | } |
- | |
246 | - | ||
247 | public function setPrivate() { |
- | |
248 | $this->visibility = 1; |
- | |
249 | } |
- | |
250 | public function isPrivate() { |
- | |
251 | return $this->visibility == 1; |
- | |
252 | } |
- | |
253 | - | ||
254 | public function setProtected() { |
- | |
255 | $this->visibility = 2; |
- | |
256 | } |
- | |
257 | public function isProtected() { |
- | |
258 | return $this->visibility == 2; |
- | |
259 | } |
- | |
260 | - | ||
261 | public function setPublic() { |
- | |
262 | $this->visibility = 3; |
- | |
263 | } |
- | |
264 | public function isPublic() { |
- | |
265 | return $this->visibility == 3; |
- | |
266 | } |
- | |
267 | - | ||
268 | public function isMethod() { |
- | |
269 | return (($this->type == ICON_TYPE_FUNCTION) || |
- | |
270 | ($this->type == ICON_TYPE_CONSTRUCTOR) || |
- | |
271 | ($this->type == ICON_TYPE_DESTRUCTOR) || |
- | |
272 | ($this->type == ICON_TYPE_MAGICMETHOD)); |
- | |
273 | } |
- | |
274 | - | ||
275 | public function reset() { |
- | |
276 | $this->type = null; |
- | |
277 | $this->visibility = 3; |
- | |
278 | $this->abstractFinal = ''; |
- | |
279 | $this->static = false; |
- | |
280 | } |
- | |
281 | - | ||
282 | public function __construct() { |
- | |
283 | $this->reset(); |
- | |
284 | } |
- | |
285 | } |
- | |
286 | - | ||
287 | class FastNodeReader { |
- | |
288 | public static function readCodeFromEditor() { |
220 | private static function stripComment($x) { |
289 | $lines = array(); |
- | |
290 | while ($f = fgets(STDIN)){ |
- | |
291 | if (trim($f) == chr(1).chr(2).chr(3).chr(4).chr(5).chr(6).chr(7).chr(8)) break; |
- | |
292 | - | ||
293 | // Signal to terminate the code explorer |
- | |
294 | if (trim($f) == chr(8).chr(7).chr(6).chr(5).chr(4).chr(3).chr(2).chr(1)) { |
- | |
295 | die("\n".chr(8).chr(7).chr(6).chr(5).chr(4).chr(3).chr(2).chr(1)."\n"); |
- | |
296 | } |
- | |
297 | - | ||
298 | $lines[] = $f; |
- | |
299 | } |
- | |
300 | return implode("", $lines); |
- | |
301 | } |
- | |
302 | } |
- | |
303 | - | ||
304 | class FastNodeWriter { |
- | |
305 | - | ||
306 | public static function outputLeafNode(/* FastPHPIcon */ $icon, $lineNo, $description) { |
- | |
307 | $imageindex = _iconCodeToIndex($icon); |
- | |
308 | return 'N'.($imageindex == -1 ? '____' : sprintf('%04s', $imageindex)). |
221 | if (substr($x, 0, 1) == '#') return trim(substr($x, 1)); |
309 | sprintf('%08s', $lineNo). |
- | |
310 | sprintf('%04s', strlen(trim($description))). |
222 | if (substr($x, 0, 2) == '//') return trim(substr($x, 2)); |
311 | trim($description). |
- | |
312 | "\n"; |
- | |
313 | } |
- | |
314 | - | ||
315 | public static function outputIncreaseLevel() { |
- | |
316 | return "I\n"; |
- | |
317 | } |
- | |
318 | - | ||
319 | public static function outputDecreaseLevel() { |
- | |
320 | return "D\n"; |
- | |
321 | } |
- | |
322 | - | ||
323 | public static function outputExit() { |
- | |
324 | return "X\n"; |
- | |
325 | } |
- | |
326 | - | ||
327 | public static function signalOutputEnd() { |
- | |
328 | return "\n".chr(1).chr(2).chr(3).chr(4).chr(5).chr(6).chr(7).chr(8)."\n"; |
223 | if (substr($x, 0, 2) == '/*') return trim(substr($x, 2, strlen($x)-4)); |
329 | } |
- | |
330 | - | ||
331 | public static function outputHeader() { |
- | |
332 | return "FAST100!"; |
- | |
333 | } |
224 | } |
334 | 225 | ||
335 | } |
- | |
336 | 226 | ||
337 | function array_peek($array) { |
227 | private static final function array_peek($array) { |
338 | if (!isset($array[count($array)-1])) return null; |
228 | if (!isset($array[count($array)-1])) return null; |
339 | return $array[count($array)-1]; |
229 | return $array[count($array)-1]; |
340 | } |
230 | } |
341 | - | ||
342 | function strip_comment($x) { |
- | |
343 | if (substr($x, 0, 1) == '#') return trim(substr($x, 1)); |
- | |
344 | if (substr($x, 0, 2) == '//') return trim(substr($x, 2)); |
- | |
345 | if (substr($x, 0, 2) == '/*') return trim(substr($x, 2, strlen($x)-4)); |
- | |
346 | } |
231 | } |
347 | 232 | ||
- | 233 | $parser = new MyFastPHPCodeExplorer($icon); |
|
- | 234 | while (true) { |
|
- | 235 | try { |
|
- | 236 | $code = FastPHPReader::readCodeFromEditor(); |
|
- | 237 | } catch (FastPHPExitSignalReceivedException $e) { |
|
- | 238 | die(); |
|
- | 239 | } |
|
- | 240 | FastPHPWriter::outputHeader(); |
|
- | 241 | $parser->handle($code); |
|
- | 242 | FastPHPWriter::outputExit(); |
|
- | 243 | FastPHPWriter::signalOutputEnd(); |
|
- | 244 | sleep(1); |
|
- | 245 | } |