/**
  * Parse the conversion table stored in the cache.
  *
  * The tables should be in blocks of the following form:
  *		-{
  *			word => word ;
  *			word => word ;
  *			...
  *		}-
  *
  *	To make the tables more manageable, subpages are allowed
  *	and will be parsed recursively if $recursive == true.
  *
  */
 function parseCachedTable($code, $subpage = '', $recursive = true)
 {
     global $wgMessageCache;
     static $parsed = array();
     if (!is_object($wgMessageCache)) {
         return array();
     }
     $key = 'Conversiontable/' . $code;
     if ($subpage) {
         $key .= '/' . $subpage;
     }
     if (array_key_exists($key, $parsed)) {
         return array();
     }
     if (strpos($code, '/') === false) {
         $txt = $wgMessageCache->get('Conversiontable', true, $code);
     } else {
         $title = Title::makeTitleSafe(NS_MEDIAWIKI, "Conversiontable/{$code}");
         if ($title && $title->exists()) {
             $article = new Article($title);
             $txt = $article->getContents();
         } else {
             $txt = '';
         }
     }
     // get all subpage links of the form
     // [[MediaWiki:conversiontable/zh-xx/...|...]]
     $linkhead = $this->mLangObj->getNsText(NS_MEDIAWIKI) . ':Conversiontable';
     $subs = StringUtils::explode('[[', $txt);
     $sublinks = array();
     foreach ($subs as $sub) {
         $link = explode(']]', $sub, 2);
         if (count($link) != 2) {
             continue;
         }
         $b = explode('|', $link[0], 2);
         $b = explode('/', trim($b[0]), 3);
         if (count($b) == 3) {
             $sublink = $b[2];
         } else {
             $sublink = '';
         }
         if ($b[0] == $linkhead && $b[1] == $code) {
             $sublinks[] = $sublink;
         }
     }
     // parse the mappings in this page
     $blocks = StringUtils::explode('-{', $txt);
     $ret = array();
     $first = true;
     foreach ($blocks as $block) {
         if ($first) {
             // Skip the part before the first -{
             $first = false;
             continue;
         }
         $mappings = explode('}-', $block, 2);
         $stripped = str_replace(array("'", '"', '*', '#'), '', $mappings[0]);
         $table = StringUtils::explode(';', $stripped);
         foreach ($table as $t) {
             $m = explode('=>', $t, 3);
             if (count($m) != 2) {
                 continue;
             }
             // trim any trailling comments starting with '//'
             $tt = explode('//', $m[1], 2);
             $ret[trim($m[0])] = trim($tt[0]);
         }
     }
     $parsed[$key] = true;
     // recursively parse the subpages
     if ($recursive) {
         foreach ($sublinks as $link) {
             $s = $this->parseCachedTable($code, $link, $recursive);
             $ret = array_merge($ret, $s);
         }
     }
     if ($this->mUcfirst) {
         foreach ($ret as $k => $v) {
             $ret[Language::ucfirst($k)] = Language::ucfirst($v);
         }
     }
     return $ret;
 }