PageRenderTime 60ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/core/src/main/php/lang.base.php

http://github.com/xp-framework/xp-framework
PHP | 694 lines | 465 code | 79 blank | 150 comment | 136 complexity | f2861807a8778e72fb7f53dd03968a4b MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /* This file provides the core for the XP framework
  3. *
  4. * $Id$
  5. */
  6. // {{{ final class xp
  7. final class xp {
  8. const CLASS_FILE_EXT= '.class.php';
  9. public static $registry = array(
  10. 'errors' => array(),
  11. 'sapi' => array(),
  12. 'class.xp' => '<xp>',
  13. 'class.null' => '<null>',
  14. 'cl.level' => 0,
  15. 'cl.inv' => array()
  16. );
  17. // {{{ public string loadClass0(string name)
  18. // Loads a class by its fully qualified name
  19. function loadClass0($class) {
  20. if (isset(xp::$registry['classloader.'.$class])) {
  21. return substr(array_search($class, xp::$registry, TRUE), 6);
  22. }
  23. foreach (xp::$registry['classpath'] as $path) {
  24. // If path is a directory and the included file exists, load it
  25. if (is_dir($path) && file_exists($f= $path.DIRECTORY_SEPARATOR.strtr($class, '.', DIRECTORY_SEPARATOR).xp::CLASS_FILE_EXT)) {
  26. $cl= 'FileSystemClassLoader';
  27. } else if (is_file($path) && file_exists($f= 'xar://'.$path.'?'.strtr($class, '.', '/').xp::CLASS_FILE_EXT)) {
  28. $cl= 'ArchiveClassLoader';
  29. } else {
  30. continue;
  31. }
  32. // Load class
  33. $package= NULL;
  34. xp::$registry['classloader.'.$class]= $cl.'://'.$path;
  35. xp::$registry['cl.level']++;
  36. $r= include($f);
  37. xp::$registry['cl.level']--;
  38. if (FALSE === $r) {
  39. unset(xp::$registry['classloader.'.$class]);
  40. continue;
  41. }
  42. // Register class name and call static initializer if available
  43. $name= ($package ? strtr($package, '.', '?').'?' : '').substr($class, (FALSE === ($p= strrpos($class, '.')) ? 0 : $p + 1));
  44. xp::$registry['class.'.$name]= $class;
  45. method_exists($name, '__static') && xp::$registry['cl.inv'][]= array($name, '__static');
  46. if (0 == xp::$registry['cl.level']) {
  47. $invocations= xp::$registry['cl.inv'];
  48. xp::$registry['cl.inv']= array();
  49. foreach ($invocations as $inv) call_user_func($inv);
  50. }
  51. return $name;
  52. }
  53. xp::error('Cannot bootstrap class '.$class.' (include_path= '.get_include_path().')');
  54. }
  55. // }}}
  56. // {{{ public string nameOf(string name)
  57. // Returns the fully qualified name
  58. static function nameOf($name) {
  59. $k= 'class.'.$name;
  60. return isset(xp::$registry[$k]) ? xp::$registry[$k] : 'php.'.$name;
  61. }
  62. // }}}
  63. // {{{ public string typeOf(var arg)
  64. // Returns the fully qualified type name
  65. static function typeOf($arg) {
  66. return is_object($arg) ? xp::nameOf(get_class($arg)) : gettype($arg);
  67. }
  68. // }}}
  69. // {{{ public string stringOf(var arg [, string indent default ''])
  70. // Returns a string representation of the given argument
  71. static function stringOf($arg, $indent= '') {
  72. static $protect= array();
  73. if (is_string($arg)) {
  74. return '"'.$arg.'"';
  75. } else if (is_bool($arg)) {
  76. return $arg ? 'true' : 'false';
  77. } else if (is_null($arg)) {
  78. return 'null';
  79. } else if ($arg instanceof null) {
  80. return '<null>';
  81. } else if (is_int($arg) || is_float($arg)) {
  82. return (string)$arg;
  83. } else if ($arg instanceof Generic && !isset($protect[(string)$arg->hashCode()])) {
  84. $protect[(string)$arg->hashCode()]= TRUE;
  85. $s= $arg->toString();
  86. unset($protect[(string)$arg->hashCode()]);
  87. return $s;
  88. } else if (is_array($arg)) {
  89. $ser= serialize($arg);
  90. if (isset($protect[$ser])) return '->{:recursion:}';
  91. $protect[$ser]= TRUE;
  92. $r= "[\n";
  93. foreach (array_keys($arg) as $key) {
  94. $r.= $indent.' '.$key.' => '.xp::stringOf($arg[$key], $indent.' ')."\n";
  95. }
  96. unset($protect[$ser]);
  97. return $r.$indent.']';
  98. } else if (is_object($arg)) {
  99. $ser= serialize($arg);
  100. if (isset($protect[$ser])) return '->{:recursion:}';
  101. $protect[$ser]= TRUE;
  102. $r= xp::nameOf(get_class($arg))." {\n";
  103. $vars= (array)$arg;
  104. foreach (array_keys($vars) as $key) {
  105. $r.= $indent.' '.$key.' => '.xp::stringOf($vars[$key], $indent.' ')."\n";
  106. }
  107. unset($protect[$ser]);
  108. return $r.$indent.'}';
  109. } else if (is_resource($arg)) {
  110. return 'resource(type= '.get_resource_type($arg).', id= '.(int)$arg.')';
  111. }
  112. }
  113. // }}}
  114. // {{{ public static void extensions(string class, string scope)
  115. // Registers extension methods for a certain scope
  116. static function extensions($class, $scope) {
  117. foreach (create(new XPClass($class))->getMethods() as $method) {
  118. if (MODIFIER_STATIC & $method->getModifiers() && $method->numParameters() > 0) {
  119. $param= $method->getParameter(0);
  120. if ('self' === $param->getName()) {
  121. self::$registry['ext'][$scope][xp::reflect($param->getTypeName())]= $class;
  122. }
  123. }
  124. }
  125. }
  126. // }}}
  127. // {{{ public void gc([string file default NULL])
  128. // Runs the garbage collector
  129. static function gc($file= NULL) {
  130. if ($file) {
  131. unset(xp::$registry['errors'][$file]);
  132. } else {
  133. xp::$registry['errors']= array();
  134. }
  135. }
  136. // }}}
  137. // {{{ public <null> null()
  138. // Runs a fatal-error safe version of NULL
  139. static function null() {
  140. return xp::$registry['null'];
  141. }
  142. // }}}
  143. // {{{ public bool errorAt(string file [, int line)
  144. // Returns whether an error occured at the specified position
  145. static function errorAt($file, $line= -1) {
  146. $errors= xp::$registry['errors'];
  147. // If no line is given, check for an error in the file
  148. if ($line < 0) return !empty($errors[$file]);
  149. // Otherwise, check for an error in the file on a certain line
  150. return !empty($errors[$file][$line]);
  151. }
  152. // }}}
  153. // {{{ public var sapi(string* sapis)
  154. // Sets an SAPI
  155. static function sapi() {
  156. foreach ($a= func_get_args() as $name) {
  157. foreach (xp::$registry['classpath'] as $path) {
  158. $filename= 'sapi'.DIRECTORY_SEPARATOR.strtr($name, '.', DIRECTORY_SEPARATOR).'.sapi.php';
  159. if (is_dir($path) && file_exists($f= $path.DIRECTORY_SEPARATOR.$filename)) {
  160. require_once($f);
  161. continue 2;
  162. } else if (is_file($path) && file_exists($f= 'xar://'.$path.'?'.strtr($filename, DIRECTORY_SEPARATOR, '/'))) {
  163. require_once($f);
  164. continue 2;
  165. }
  166. }
  167. xp::error('Cannot open SAPI '.$name.' (include_path='.get_include_path().')');
  168. }
  169. xp::$registry['sapi']= $a;
  170. }
  171. // }}}
  172. // {{{ internal var registry(var args*)
  173. // Stores static data
  174. static function registry() {
  175. switch (func_num_args()) {
  176. case 0: return xp::$registry;
  177. case 1: return @xp::$registry[func_get_arg(0)];
  178. case 2: xp::$registry[func_get_arg(0)]= func_get_arg(1); break;
  179. }
  180. return NULL;
  181. }
  182. // }}}
  183. // {{{ internal string reflect(string type)
  184. // Retrieve type literal for a given type name
  185. static function reflect($type) {
  186. if ('string' === $type || 'int' === $type || 'double' === $type || 'bool' == $type) {
  187. return '?'.$type;
  188. } else if ('var' === $type) {
  189. return $type;
  190. } else if ('[]' === substr($type, -2)) {
  191. return '?'.xp::reflect(substr($type, 0, -2));
  192. } else if ('[:' === substr($type, 0, 2)) {
  193. return '?'.xp::reflect(substr($type, 2, -1));
  194. } else if (FALSE !== ($p= strpos($type, '<'))) {
  195. $l= xp::reflect(substr($type, 0, $p)).'??';
  196. for ($args= substr($type, $p+ 1, -1).',', $o= 0, $brackets= 0, $i= 0, $s= strlen($args); $i < $s; $i++) {
  197. if (',' === $args{$i} && 0 === $brackets) {
  198. $l.= xp::reflect(ltrim(substr($args, $o, $i- $o))).'?';
  199. $o= $i+ 1;
  200. } else if ('<' === $args{$i}) {
  201. $brackets++;
  202. } else if ('>' === $args{$i}) {
  203. $brackets--;
  204. }
  205. }
  206. return substr($l, 0, -1);
  207. } else {
  208. $l= array_search($type, xp::$registry, TRUE);
  209. return $l ? substr($l, 6) : substr($type, (FALSE === $p= strrpos($type, '.')) ? 0 : $p+ 1);
  210. }
  211. }
  212. // }}}
  213. // {{{ internal void error(string message)
  214. // Throws a fatal error and exits with exitcode 61
  215. static function error($message) {
  216. restore_error_handler();
  217. trigger_error($message, E_USER_ERROR);
  218. exit(0x3d);
  219. }
  220. }
  221. // }}}
  222. // {{{ final class null
  223. class null {
  224. // {{{ public object __construct(void)
  225. // Constructor to avoid magic __call invokation
  226. public function __construct() {
  227. if (isset(xp::$registry['null'])) {
  228. throw new IllegalAccessException('Cannot create new instances of xp::null()');
  229. }
  230. }
  231. // {{{ public void __clone(void)
  232. // Clone interceptor
  233. public function __clone() {
  234. throw new NullPointerException('Object cloning intercepted.');
  235. }
  236. // }}}
  237. // {{{ magic var __call(string name, var[] args)
  238. // Call proxy
  239. function __call($name, $args) {
  240. throw new NullPointerException('Method.invokation('.$name.')');
  241. }
  242. // }}}
  243. // {{{ magic void __set(string name, var value)
  244. // Set proxy
  245. function __set($name, $value) {
  246. throw new NullPointerException('Property.write('.$name.')');
  247. }
  248. // }}}
  249. // {{{ magic var __get(string name)
  250. // Set proxy
  251. function __get($name) {
  252. throw new NullPointerException('Property.read('.$name.')');
  253. }
  254. // }}}
  255. }
  256. // }}}
  257. // {{{ final class xploader
  258. class xarloader {
  259. public
  260. $position = 0,
  261. $archive = '',
  262. $filename = '';
  263. // {{{ static var[] acquire(string archive)
  264. // Archive instance handling pool function, opens an archive and reads header only once
  265. static function acquire($archive) {
  266. static $archives= array();
  267. static $unpack= array(
  268. 1 => 'a80id/a80*filename/a80*path/V1size/V1offset/a*reserved',
  269. 2 => 'a240id/V1size/V1offset/a*reserved'
  270. );
  271. if (!isset($archives[$archive])) {
  272. $archives[$archive]= array();
  273. $current= &$archives[$archive];
  274. $current['handle']= fopen($archive, 'rb');
  275. $header= unpack('a3id/c1version/V1indexsize/a*reserved', fread($current['handle'], 0x0100));
  276. if ('CCA' != $header['id']) raise('lang.FormatException', 'Malformed archive '.$archive);
  277. for ($current['index']= array(), $i= 0; $i < $header['indexsize']; $i++) {
  278. $entry= unpack(
  279. $unpack[$header['version']],
  280. fread($current['handle'], 0x0100)
  281. );
  282. $current['index'][$entry['id']]= array($entry['size'], $entry['offset'], $i);
  283. }
  284. }
  285. return $archives[$archive];
  286. }
  287. // }}}
  288. // {{{ function bool stream_open(string path, string mode, int options, string opened_path)
  289. // Open the given stream and check if file exists
  290. function stream_open($path, $mode, $options, $opened_path) {
  291. sscanf($path, 'xar://%[^?]?%[^$]', $archive, $file);
  292. $this->archive= urldecode($archive);
  293. $this->filename= $file;
  294. $current= self::acquire($this->archive);
  295. return isset($current['index'][$this->filename]);
  296. }
  297. // }}}
  298. // {{{ string stream_read(int count)
  299. // Read $count bytes up-to-length of file
  300. function stream_read($count) {
  301. $current= self::acquire($this->archive);
  302. if (!isset($current['index'][$this->filename])) return FALSE;
  303. if ($current['index'][$this->filename][0] == $this->position || 0 == $count) return FALSE;
  304. fseek($current['handle'], 0x0100 + sizeof($current['index']) * 0x0100 + $current['index'][$this->filename][1] + $this->position, SEEK_SET);
  305. $bytes= fread($current['handle'], min($current['index'][$this->filename][0]- $this->position, $count));
  306. $this->position+= strlen($bytes);
  307. return $bytes;
  308. }
  309. // }}}
  310. // {{{ bool stream_eof()
  311. // Returns whether stream is at end of file
  312. function stream_eof() {
  313. $current= self::acquire($this->archive);
  314. return $this->position >= $current['index'][$this->filename][0];
  315. }
  316. // }}}
  317. // {{{ <string,int> stream_stat()
  318. // Retrieve status of stream
  319. function stream_stat() {
  320. $current= self::acquire($this->archive);
  321. return array(
  322. 'size' => $current['index'][$this->filename][0],
  323. 'dev' => crc32($this->archive),
  324. 'ino' => $current['index'][$this->filename][2]
  325. );
  326. }
  327. // }}}
  328. // {{{ bool stream_seek(int offset, int whence)
  329. // Callback for fseek
  330. function stream_seek($offset, $whence) {
  331. switch ($whence) {
  332. case SEEK_SET: $this->position= $offset; break;
  333. case SEEK_CUR: $this->position+= $offset; break;
  334. case SEEK_END:
  335. $current= self::acquire($this->archive);
  336. $this->position= $current['index'][$this->filename][0] + $offset;
  337. break;
  338. }
  339. return TRUE;
  340. }
  341. // }}}
  342. // {{{ int stream_tell
  343. // Callback for ftell
  344. function stream_tell() {
  345. return $this->position;
  346. }
  347. // }}}
  348. // {{{ <string,int> url_stat(string path)
  349. // Retrieve status of url
  350. function url_stat($path) {
  351. sscanf($path, 'xar://%[^?]?%[^$]', $archive, $file);
  352. $archive= urldecode($archive);
  353. $current= self::acquire($archive);
  354. if (!isset($current['index'][$file])) return FALSE;
  355. return array(
  356. 'size' => $current['index'][$file][0],
  357. 'dev' => crc32($archive),
  358. 'ino' => $current['index'][$file][2]
  359. );
  360. }
  361. // }}}
  362. }
  363. // }}}
  364. // {{{ internal void __error(int code, string msg, string file, int line)
  365. // Error callback
  366. function __error($code, $msg, $file, $line) {
  367. if (0 == error_reporting() || is_null($file)) return;
  368. if (E_RECOVERABLE_ERROR == $code) {
  369. throw new IllegalArgumentException($msg.' @ '.$file.':'.$line);
  370. } else {
  371. $bt= debug_backtrace();
  372. $class= (isset($bt[1]['class']) ? $bt[1]['class'] : NULL);
  373. $method= (isset($bt[1]['function']) ? $bt[1]['function'] : NULL);
  374. if (!isset(xp::$registry['errors'][$file][$line][$msg])) {
  375. xp::$registry['errors'][$file][$line][$msg]= array(
  376. 'class' => $class,
  377. 'method' => $method,
  378. 'cnt' => 1
  379. );
  380. } else {
  381. xp::$registry['errors'][$file][$line][$msg]['cnt']++;
  382. }
  383. }
  384. }
  385. // }}}
  386. // {{{ void uses (string* args)
  387. // Uses one or more classes
  388. function uses() {
  389. $scope= NULL;
  390. foreach (func_get_args() as $str) {
  391. $class= xp::$registry['loader']->loadClass0($str);
  392. if (method_exists($class, '__import')) {
  393. if (NULL === $scope) {
  394. $trace= debug_backtrace();
  395. $scope= xp::reflect($trace[2]['args'][0]);
  396. }
  397. call_user_func(array($class, '__import'), $scope);
  398. }
  399. }
  400. }
  401. // }}}
  402. // {{{ void raise (string classname, var* args)
  403. // throws an exception by a given class name
  404. function raise($classname) {
  405. try {
  406. $class= XPClass::forName($classname);
  407. } catch (ClassNotFoundException $e) {
  408. xp::error($e->getMessage());
  409. }
  410. $a= func_get_args();
  411. throw call_user_func_array(array($class, 'newInstance'), array_slice($a, 1));
  412. }
  413. // }}}
  414. // {{{ void finally (void)
  415. // Syntactic sugar. Intentionally empty
  416. function finally() {
  417. }
  418. // }}}
  419. // {{{ Generic cast (Generic expression, string type)
  420. // Casts an expression.
  421. function cast(Generic $expression= NULL, $type) {
  422. if (NULL === $expression) {
  423. return xp::null();
  424. } else if (XPClass::forName($type)->isInstance($expression)) {
  425. return $expression;
  426. }
  427. raise('lang.ClassCastException', 'Cannot cast '.xp::typeOf($expression).' to '.$type);
  428. }
  429. // {{{ proto bool is(string type, var object)
  430. // Checks whether a given object is an instance of the type given
  431. function is($type, $object) {
  432. if (NULL === $type) {
  433. return $object instanceof null;
  434. } else if ('int' === $type) {
  435. return is_int($object);
  436. } else if ('double' === $type) {
  437. return is_double($object);
  438. } else if ('string' === $type) {
  439. return is_string($object);
  440. } else if ('bool' === $type) {
  441. return is_bool($object);
  442. } else if ('var' === $type) {
  443. return TRUE;
  444. } else if ('[]' === substr($type, -2)) {
  445. if (!is_array($object) || (!empty($object) && !is_int(key($object)))) return FALSE;
  446. $type= substr($type, 0, -2);
  447. foreach ($object as $element) {
  448. if (!is($type, $element)) return FALSE;
  449. }
  450. return TRUE;
  451. } else if ('[:' === substr($type, 0, 2)) {
  452. if (!is_array($object) || (!empty($object) && !is_string(key($object)))) return FALSE;
  453. $type= substr($type, 2, -1);
  454. foreach ($object as $element) {
  455. if (!is($type, $element)) return FALSE;
  456. }
  457. return TRUE;
  458. } else {
  459. $type= xp::reflect($type);
  460. return $object instanceof $type;
  461. }
  462. }
  463. // }}}
  464. // {{{ proto void delete(&lang.Object object)
  465. // Destroys an object
  466. function delete(&$object) {
  467. $object= NULL;
  468. }
  469. // }}}
  470. // {{{ proto void with(expr)
  471. // Syntactic sugar. Intentionally empty
  472. function with() {
  473. }
  474. // }}}
  475. // {{{ proto deprecated var ref(var object)
  476. // Creates a "reference" to an object
  477. function ref(&$object) {
  478. return array(&$object);
  479. }
  480. // }}}
  481. // {{{ proto deprecated &var deref(&mixed expr)
  482. // Dereferences an expression
  483. function &deref(&$expr) {
  484. if (is_array($expr)) return $expr[0]; else return $expr;
  485. }
  486. // }}}
  487. // {{{ proto var this(var expr, var offset)
  488. // Indexer access for a given expression
  489. function this($expr, $offset) {
  490. return $expr[$offset];
  491. }
  492. // }}}
  493. // {{{ proto lang.Object newinstance(string spec, var[] args, string bytes)
  494. // Anonymous instance creation
  495. function newinstance($spec, $args, $bytes) {
  496. static $u= 0;
  497. // Check for an anonymous generic
  498. if (strstr($spec, '<')) {
  499. $type= Type::forName($spec)->literal();
  500. } else {
  501. $type= xp::reflect(strstr($spec, '.') ? $spec : xp::nameOf($spec));
  502. if (!class_exists($type, FALSE) && !interface_exists($type, FALSE)) {
  503. xp::error(xp::stringOf(new Error('Class "'.$spec.'" does not exist')));
  504. // Bails
  505. }
  506. }
  507. $name= $type.'?'.(++$u);
  508. // Checks whether an interface or a class was given
  509. $cl= DynamicClassLoader::instanceFor(__FUNCTION__);
  510. if (interface_exists($type)) {
  511. $cl->setClassBytes($name, 'class '.$name.' extends Object implements '.$type.' '.$bytes);
  512. } else {
  513. $cl->setClassBytes($name, 'class '.$name.' extends '.$type.' '.$bytes);
  514. }
  515. $cl->loadClass0($name);
  516. // Build paramstr for evaluation
  517. for ($paramstr= '', $i= 0, $m= sizeof($args); $i < $m; $i++) {
  518. $paramstr.= ', $args['.$i.']';
  519. }
  520. return eval('return new '.$name.'('.substr($paramstr, 2).');');
  521. }
  522. // }}}
  523. // {{{ lang.Generic create(var spec)
  524. // Creates a generic object
  525. function create($spec) {
  526. if ($spec instanceof Generic) return $spec;
  527. // Parse type specification: "new " TYPE "()"?
  528. // TYPE:= B "<" ARGS ">"
  529. // ARGS:= TYPE [ "," TYPE [ "," ... ]]
  530. $b= strpos($spec, '<');
  531. $base= substr($spec, 4, $b- 4);
  532. $typeargs= Type::forNames(substr($spec, $b+ 1, strrpos($spec, '>')- $b- 1));
  533. // BC check: For classes with __generic field, instanciate without
  534. // invoking the constructor and pass type information. This is done
  535. // so that the constructur can already use generic types.
  536. $class= XPClass::forName(strstr($base, '.') ? $base : xp::nameOf($base));
  537. if ($class->hasField('__generic')) {
  538. $__id= microtime();
  539. $name= xp::reflect($classname);
  540. $instance= unserialize('O:'.strlen($name).':"'.$name.'":1:{s:4:"__id";s:'.strlen($__id).':"'.$__id.'";}');
  541. foreach ($typeargs as $type) {
  542. $instance->__generic[]= xp::reflect($type->getName());
  543. }
  544. // Call constructor if available
  545. if (method_exists($instance, '__construct')) {
  546. $a= func_get_args();
  547. call_user_func_array(array($instance, '__construct'), array_slice($a, 1));
  548. }
  549. return $instance;
  550. }
  551. // BC: Wrap IllegalStateExceptions into IllegalArgumentExceptions
  552. try {
  553. $type= $class->newGenericType($typeargs);
  554. } catch (IllegalStateException $e) {
  555. throw new IllegalArgumentException($e->getMessage());
  556. }
  557. // Instantiate
  558. if ($type->hasConstructor()) {
  559. $args= func_get_args();
  560. try {
  561. return $type->getConstructor()->newInstance(array_slice($args, 1));
  562. } catch (TargetInvocationException $e) {
  563. throw $e->getCause();
  564. }
  565. } else {
  566. return $type->newInstance();
  567. }
  568. }
  569. // }}}
  570. // {{{ lang.Type typeof(mixed arg)
  571. // Returns type
  572. function typeof($arg) {
  573. if ($arg instanceof Generic) {
  574. return $arg->getClass();
  575. } else if (NULL === $arg) {
  576. return Type::$VOID;
  577. } else if (is_array($arg)) {
  578. return 0 === key($arg) ? ArrayType::forName('var[]') : MapType::forName('[:var]');
  579. } else {
  580. return Type::forName(gettype($arg));
  581. }
  582. }
  583. // }}}
  584. // {{{ initialization
  585. error_reporting(E_ALL);
  586. // Constants
  587. define('LONG_MAX', PHP_INT_MAX);
  588. define('LONG_MIN', -PHP_INT_MAX - 1);
  589. // Hooks
  590. set_error_handler('__error');
  591. // Get rid of magic quotes
  592. get_magic_quotes_gpc() && xp::error('[xp::core] magic_quotes_gpc enabled');
  593. date_default_timezone_set(ini_get('date.timezone')) || xp::error('[xp::core] date.timezone not configured properly.');
  594. ini_set('magic_quotes_runtime', FALSE);
  595. // Registry initialization
  596. xp::$registry['null']= new null();
  597. xp::$registry['loader']= new xp();
  598. xp::$registry['classpath']= explode(PATH_SEPARATOR, get_include_path());
  599. // Register stream wrapper for .xar class loading
  600. stream_wrapper_register('xar', 'xarloader');
  601. // Omnipresent classes
  602. uses(
  603. 'lang.Object',
  604. 'lang.Error',
  605. 'lang.XPException',
  606. 'lang.XPClass',
  607. 'lang.NullPointerException',
  608. 'lang.IllegalAccessException',
  609. 'lang.IllegalArgumentException',
  610. 'lang.IllegalStateException',
  611. 'lang.FormatException',
  612. 'lang.ClassLoader'
  613. );
  614. // }}}
  615. ?>