Location: PHPKode > projects > Pieforms > pieforms-php5-0.2.2/doc/geshi/class.geshi.php
<?php
/**
 * GeSHi - Generic Syntax Highlighter
 * <pre>
 *   File:   class.geshi.php
 *   Author: Nigel McNie
 *   E-mail: hide@address.com
 * </pre>
 *
 * For information on how to use GeSHi, please consult the documentation
 * found in the docs/ directory, or online at http://geshi.org/docs/
 *
 * This program is part of GeSHi.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 *
 * @package    geshi
 * @subpackage core
 * @author     Nigel McNie <hide@address.com>
 * @author     Knut A. Wikström <hide@address.com>
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
 * @copyright  (C) 2004 - 2006 Nigel McNie
 * @version    $Id: class.geshi.php 910 2007-02-22 00:30:59Z benbe $
 *
 */

//
// Set error level to E_ALL. This stops strict warnings
// about syntax in PHP5, which we are not interested in
//
$geshi_old_reporting_level = error_reporting(E_ALL);

/** GeSHi Version */
define('GESHI_VERSION', '1.1.2alpha4dev');

/** Set the correct directory separator */
define('GESHI_DIR_SEP', DIRECTORY_SEPARATOR);

// Define the root directory for the GeSHi code tree
if (!defined('GESHI_ROOT')) {
    /** The root directory for GeSHi (where class.geshi.php is located) */
    define('GESHI_ROOT', dirname(__FILE__) . '/');
}

/**#@+
 * @access private
 */
/** The data directory for GeSHi */
define('GESHI_DATA_ROOT', GESHI_ROOT . 'geshi' . '/');
/** The classes directory for GeSHi */
define('GESHI_CLASSES_ROOT', GESHI_DATA_ROOT . 'classes' . '/');
/** The languages directory for GeSHi */
define('GESHI_LANGUAGES_ROOT', GESHI_DATA_ROOT . 'languages' . '/');
/** The context files directory for GeSHi */
define('GESHI_CONTEXTS_ROOT', GESHI_DATA_ROOT . 'contexts' . '/');
/** The theme files directory for GeSHi */
define('GESHI_THEMES_ROOT', GESHI_DATA_ROOT . 'themes' . '/');
/** The renderers directory for GeSHi */
define('GESHI_RENDERERS_ROOT', GESHI_CLASSES_ROOT . 'renderers' . '/');
/**#@-*/

/** Get required functions */
require GESHI_DATA_ROOT . 'functions.geshi.php';

/** Get styler class */
require GESHI_CLASSES_ROOT . 'class.geshistyler.php';

/** Get context class */
require GESHI_CLASSES_ROOT . 'class.geshicontext.php';

/** Get code context class */
require GESHI_CLASSES_ROOT . 'class.geshicodecontext.php';

//
// Although this classe may not be used by a particular language,
// there's a very good chance that it will be, so we include it
// now to save on require_once calls later. This improves performance
// when using an opcode cache/accelerator.
//

/** Get string context class */
require GESHI_CLASSES_ROOT . 'class.geshistringcontext.php';

//
// Constants
//

// These provide BACKWARD COMPATIBILITY ONLY
// Use New Method setStyles(mixed identifiers, string styles);
// e.g. setStyles('html/tag', 'styles');
//      setStyles(array('html/tag', 'html/css-delimiters'), 'style');

// @todo these may yet disappear, they're not used yet
/** Used to mark a context as having no equivalence in 1.0.X */
define('GESHI_STYLE_NONE', 0);
/** Used to mark a context as being like a number in 1.0.X */
define('GESHI_STYLE_NUMBERS', 1);
/** Used to mark a context as being like a comment in 1.0.X */
define('GESHI_STYLE_COMMENTS', 2);
/** Used to mark a context as being like a string in 1.0.X */
define('GESHI_STYLE_STRINGS', 3);
/** Used to mark a context as being like a symbol in 1.0.X */
define('GESHI_STYLE_SYMBOLS', 4);
/** Used to mark a context as being like a method in 1.0.X */
define('GESHI_STYLE_METHODS', 5);

// Security
if (!defined('GESHI_ALLOW_SYMLINK_PATHS')) {
    /** Whether to allow paths to contain symlinks */
    define('GESHI_ALLOW_SYMLINK_PATHS', false);
}

// Error related constants, not needed by users of GeSHi
// @todo won't be used anymore, just define the old ones for BC.
// Even they will disappear in 2.0

/** No error has occured */
define('GESHI_ERROR_NONE', 0);

/**#@+
 * @access private
 */

// Constants for specifying who (out of the parent or child) highlights the delimiter
// between the parent and the child. Note that if you view the numbers as two bit binary,
// a 1 indicates where the child parses and a 0 indicates where the parent should parse.
// The default is GESHI_CHILD_PARSE_BOTH
/** The child should parse neither delimiter (parent parses both) */
define('GESHI_CHILD_PARSE_NONE', 0);
/** The child should parse the right (end) delimiter, the parent should parse the left delimiter */
define('GESHI_CHILD_PARSE_RIGHT', 1);
/** The child should parse the left (beginning) delimiter, the parent should parse the right delimiter */
define('GESHI_CHILD_PARSE_LEFT', 2);
/** The child should parse both delimiters (default) */
define('GESHI_CHILD_PARSE_BOTH', 3);

// Tokenise levels
define('GESHI_COMPLEX_NO', 0);
define('GESHI_COMPLEX_PASSALL', 1);
define('GESHI_COMPLEX_TOKENISE', 2);
define('GESHI_COMPLEX_TOKENIZE', GESHI_COMPLEX_TOKENISE);

/**#@-*/


/**
 * The GeSHi class
 *
 * This class provides the public interface. The actual highligting is offloaded
 * to elsewhere.
 *
 * @package    geshi
 * @subpackage core
 * @author     Nigel McNie <hide@address.com>
 * @version    $Revision: 910 $
 * @since      1.0.0
 * @todo       [blocking 1.1.9] Better documentation for this class
 */
class GeSHi
{

    // {{{ properties

    /**#@+
     * @access private
     */

    /**
     * The source code to parse
     *
     * @var string
     */
    var $_source = '';

    /**
     * The name of the language to use when parsing the source
     *
     * @var string
     */
    var $_language = '';

    /**
     * The humanised version of the language name
     *
     * @todo used?
     */
    //var $_humanLanguageName = '';

    /**
     * The error code of any error that has occured
     *
     * @var int
     */
    //var $_error = GESHI_ERROR_NONE;

    /**
     * The root context to use for parsing the source
     *
     * @var GeSHiContext
     */
    var $_rootContext = null;

    /**
     * The GeSHiStyler object used by this class and all contexts for
     * assisting parsing.
     *
     * @var GeSHiStyler
     */
    var $_styler = null;

    /**
     * Timing information for the last code parsing
     *
     * @var array
     */
    var $_times = array();

    /**#@-*/

    // }}}
    // {{{ GeSHi()

    /**
     * Sets the source and language name of the source to parse
     *
     * Also sets up other defaults, such as the default encoding
     *
     * <b>USAGE:</b>
     *
     * <code> $geshi =& new GeSHi($source, $language);
     * // Various API calls... (todo: better examples)
     * $code = $geshi->parseCode();</code>
     *
     * @param string The source code to highlight
     * @param string The language to highlight the source with
     * @param string The path to the GeSHi data files. <b>This is no longer used!</b> The path is detected
     *               automatically by GeSHi, this paramter is only included for backward compatibility. If
     *               you want to set the path to the GeSHi data directories yourself, you should define the
     *               GESHI_ROOT constant before including class.geshi.php.
     * @since 1.0.0
     */
    function GeSHi ($source, $language_name, $path = '')
    {
        // Initialise timing
        // @todo [blocking 1.1.5] have to re-initialise timing if this object used many times
        $this->_initialiseTiming();

        // Create a new styler
        $this->_styler =& geshi_styler(true);

        // Set the initial source/language
        $this->setSource($source);
        $this->setLanguage($language_name);

        // @todo [blocking 1.1.5] Make third parameter an option array thing (maybe)
        //$this->setOutputFormat(GESHI_OUTPUT_HTML);
        //$this->setEncoding(GESHI_DEFAULT_ENCODING);

    }

    // }}}
    // {{{ setSource()

    /**
     * Sets the source code to highlight
     *
     * @param string The source code to highlight
     * @since 1.0.0
     */
    function setSource ($source)
    {
        $this->_source = strval($source);
    }

    // }}}
    // {{{ setLanguage()

    /**
     * Sets the language to use for highlighting
     *
     * @param string The language to use for highlighting
     * @since 1.0.0
     */
    function setLanguage ($language_name)
    {
        // Make a legal language name
        $this->_language = GeSHi::_cleanLanguageName($language_name);
        $this->_styler->language = $this->_language;
    }

    // }}}
    // {{{ getTime()

    /**
     * Returns various timings related to this object.
     *
     * For example, how long it took to load a specific context,
     * or parse the source code.
     *
     * You can pass a string to this method, it will return various timings based
     * on what string you pass:
     *
     * <ul>
     *   <li>If you pass <b>'total'</b> (default), you will get the time it took to
     *   load, parse and post-process the last call to {@link GeSHi::parseCode()}.</li>
     *   <li>If you pass <b>'pre'</b>, you will get the time it took to load the last
     *   language. If caching of the root context is enabled, then this time will likely
     *   be close to zero if you are calling this method after second and subsequent calls
     *   to {@link GeSHi::parseCode()}.</li>
     *   <li>If you pass <b>'parse'</b>, you will get the time it took to parse the last
     *   time {@link GeSHi::parseCode()} was called.
     * </ul>
     *
     * @param  string What time you want to access
     * @return mixed The time if there is a time, else false if there was an error
     * @since  1.1.0
     */
    function getTime ($type = 'total')
    {
        if (isset($this->_times[$type])) {
            $start = explode(' ', $this->_times[$type][0]);
            $end   = explode(' ', $this->_times[$type][1]);
            return $end[0] + $end[1] - $start[0] - $start[1];
        } elseif ('total' == $type) {
            return $this->getTime('pre') + $this->getTime('parse') + $this->getTime('post');
        }
        trigger_error('GeSHi Error: type passed to getTime() is invalid');
        return false;
    }

    // }}}
    // {{{ setStyles()

    /**
     * Sets styles of contexts in the source code
     *
     * @param string The selector to use, this is the style name of a context. Example: php/php
     * @param string The CSS styles to apply to the context
     * @since 1.1.1
     */
    function setStyles ($selector, $styles)
    {
        geshi_dbg('GeSHi::setStyles(' . $selector . ', ' . $styles . ')');
        $this->_styler->loadStyles('', true);
        $this->_styler->setRawStyle($selector, $styles);
    }

    // }}}
    // {{{ setTheme()

    /**
     * Sets the theme to use
     *
     * This method can take a list of themes as well as an array or just one theme, e.g.:
     *
     * <code> $geshi->setTheme('theme');
     * $geshi->setTheme(array('theme1', 'theme2'));
     * $geshi->setTheme('theme1', 'theme2');</code>
     *
     * (note the difference between the second and third calls)
     *
     * @param mixed The theme name(s)
     * @since 1.1.1
     */
    function setTheme ($themes)
    {
        // Passed in reverse order so priority is preserved
        for ($i = func_num_args() - 1; $i >= 0; $i--) {
            $this->_styler->useThemes(GeSHi::_clean(func_get_arg($i)));
        }
    }

    // }}}
    // {{{

    /**
     * Sets the renderer to use
     *
     * @param GeSHiRenderer $renderer The renderer to use
     */
    function setRenderer (&$renderer) {
        $this->_styler->setRenderer($renderer);
    }

    // }}}
    // {{{ getSupportedLanguages()

    /**
     * @todo document this function
     * @todo This and other methods share a lot of directory traversal
     * functionality, which could be split out somehow.
     * @todo actually, this should be implemented using a registry
     */
    function getSupportedLanguages ($return_human = false)
    {
        $languages = array();

        $ignore = array('.', '..', 'CVS');
        $dh = opendir(GESHI_LANGUAGES_ROOT);
        while (false !== ($dir = readdir($dh))) {
            if (in_array($dir, $ignore) || is_file(GESHI_LANGUAGES_ROOT . $dir)) continue;
            // Check the directory for the dialect files
            $ldh = opendir(GESHI_LANGUAGES_ROOT . $dir);
            while (false !== ($file = readdir($ldh))) {
                if (in_array($file, $ignore) || is_dir(GESHI_LANGUAGES_ROOT . "$dir/$file") || substr($file, -4) != '.php') continue;

                // Found a language file
                $file = substr($file, 0, -4);
                if ('common' == $file || 'class' == substr($file, 0, 5)) continue;

                if ($return_human) {
                    $languages["$dir/$file"] = GeSHi::getHumanLanguageName("$dir/$file");
                } else {
                    $languages[] = "$dir/$file";
                }
            }
        }

        return $languages;
    }

    // }}}
    // {{{ getSupportedThemes()

    /**
     * Returns every theme supported by this installation of GeSHi
     *
     * @param  bool $return_human  If <kbd>true</kbd>, the array returned is of
     *                             the form <kbd>theme_name => human name</kbd>,
     *                             otherwise it is an array of <kbd>theme_name</kbd>s
     * @return array A list of themes supported by GeSHi
     * @static
     * @since  1.1.1
     * @todo   This is expensive, possibly cache?
     */
    function getSupportedThemes ($return_human = false)
    {
        $themes = array();

        $ignore = array('.', '..', 'CVS');
        $dh = opendir(GESHI_THEMES_ROOT);
        while (false !== ($theme_folder = readdir($dh))) {
            if (in_array($theme_folder, $ignore) || is_file(GESHI_THEMES_ROOT . $theme_folder)) continue;
            if ($return_human) {
                $themes[$theme_folder] = GeSHi::getHumanThemeName($theme_folder);
            } else {
                $themes[] = $theme_folder;
            }
        }

        return $themes;
    }

    // }}}
    // {{{ themesSupportedBy()

    /**
     * Returns the themes supported by the given language
     *
     * The names returned are in the form that GeSHi reads them, i.e. they
     * are not nice human strings. If you want the human form, use
     * {@link GeSHi::getHumanThemeName()} on each name returned.
     *
     * @param  string  $language The language to get supported themes for
     * @param  boolean $return_human If <kbd>true</kbd>, returns an array of
     *                               theme name => human-readable name. Otherwise,
     *                               just return an array of theme names.
     * @return array A list of themes supported by the language. Note that
     *               they are _not_ in preferred order
     * @static
     * @since 1.1.1
     * @todo  Make them in preferred order?
     * @todo  Expensive, maybe cache?
     */
    function themesSupportedBy ($language, $return_human = false)
    {
        $themes = array();
        //geshi_dbg('GeSHi::themesSupportedBy(' . $language . ')', GESHI_DBG_API);
        $language = GeSHi::_cleanLanguageName($language);
        //geshi_dbg('  language now ' . $language, GESHI_DBG_API);

        $dh = opendir(GESHI_THEMES_ROOT);
        while (false !== ($theme_folder = readdir($dh))) {
            if ('.' == $theme_folder || '..' == $theme_folder) continue;
            if (is_readable(GESHI_THEMES_ROOT . $theme_folder
                . '/' . $language . '.php')) {
                if ($return_human) {
                    $themes[$theme_folder] = GeSHi::getHumanThemeName($theme_folder);
                } else {
                    $themes[] = $theme_folder;
                }

                // Check for subthemes
                $dh2 = opendir(GESHI_THEMES_ROOT . $theme_folder);
                while (false !== ($subtheme_folder = readdir($dh2))) {
                    if ('.' == $subtheme_folder || '..' == $subtheme_folder
                        || !is_dir(GESHI_THEMES_ROOT . $theme_folder . '/' . $subtheme_folder)) continue;
                    if (is_readable(GESHI_THEMES_ROOT . $theme_folder . '/' . $subtheme_folder
                        . '/' . $language . '.php')) {
                        $subtheme_name = "$theme_folder/$subtheme_folder";
                        if ($return_human) {
                            $themes[$subtheme_name] = GeSHi::getHumanThemeName($subtheme_name);
                        } else {
                            $themes[] = $subtheme_name;
                        }
                    }
                }
            }
        }

        return $themes;
    }

    // }}}
    // {{{ languagesSupportedBy()

    /**
     * Returns the languages supported by the given theme
     *
     * @param  string $theme The theme to get supported languages for
     * @return array  A list of languages supported by the theme, in the form:
     * <pre> array(
     *      'language' => array('dialect', 'dialect', ...),
     *      'language' => array('dialect', ...)
     * );</pre>
     *
     * @static
     * @since 1.1.1
     */
    function languagesSupportedBy ($theme)
    {
        //geshi_dbg('GeSHi::languagesSupportedBy(' . $theme . ')', GESHI_DBG_API);
        $languages = array();
        $theme = GeSHi::_clean($theme);
        //geshi_dbg('  theme now ' . $theme, GESHI_DBG_API);
        $theme_file = GESHI_THEMES_ROOT . $theme . '/' . 'themeinfo.php';
        if (is_readable($theme_file)) {
            require $theme_file;
            return $languages;
        }
        return array();
    }

    // }}}
    // {{{ getHumanLanguageName()

    /**
     * Given a language name, return a human version of it
     *
     * @param  string $language The language name to get the human version of
     * @return string The human language name, or <kbd>false</kbd> if the
     *                language does not exist
     * @static
     * @todo actually implement this function
     * @since 1.1.2
     */
    function getHumanLanguageName ($language)
    {
        $human_name = '';
        $language = GeSHi::_clean($language);
        return $language;
    }

    // }}}
    // {{{ getHumanThemeName()

    /**
     * Given a theme name, return a human version of it
     *
     * @param  string $theme The theme name to get the human version of
     * @return string The human theme name, or <kbd>false</kbd> if the
     *                theme does not exist
     * @static
     * @since 1.1.1
     */
    function getHumanThemeName ($theme)
    {
        $human_name = '';
        $theme = GeSHi::_clean($theme);
        $theme_file = GESHI_THEMES_ROOT . $theme . '/' . 'themeinfo.php';
        if (is_readable($theme_file)) {
            require $theme_file;
            return $human_name;
        }
        return false;
    }

    // }}}
    // {{{ themeSupportsLanguage()

    /**
     * Given a theme and language, returns whether the them
     * supports that language
     *
     * @param  string $theme    The name of the theme to check
     * @param  string $language The name of the language to check
     * @return boolean          Whether the language supports the theme
     * @static
     * @since 1.1.1
     */
    function themeSupportsLanguage ($theme, $language)
    {
        $language = GeSHi::_cleanLanguageName($language);
        return geshi_can_include(GESHI_THEMES_ROOT . $theme . '/' . $language . '.php');
    }

    // }}}
    // {{{ getVersion()

    /**
     * Returns the version of this GeSHi
     *
     * @return string The version of this GeSHi
     * @static
     * @since  1.1.0
     */
    function getVersion ()
    {
        return GESHI_VERSION;
    }

    // }}}
    // {{{ parseCode()

    /**
     * Syntax-highlights the source code
     *
     * @return string The source code, highlighted
     * @since 1.0.0
     */
    function parseCode ()
    {
        $this->_times['pre'][0] = microtime();
        $result = $this->_parsePreProcess();
        $this->_times['pre'][1] = $this->_times['parse'][0] = microtime();

        if ($result) {
            // The important bit - parse the code
            $this->_rootContext->parseCode($this->_source);
        }

        $this->_times['parse'][1] = $this->_times['post'][0] = microtime();
        $result = $this->_parsePostProcess();
        $this->_times['post'][1] = microtime();

        return $result;
    }

    // }}}
    // {{{ hsc()

    /**
     * Secure replacement for PHP built-in function htmlspecialchars().
     *
     * See ticket #427 (http://wush.net/trac/wikka/ticket/427) for the rationale
     * for this replacement function.
     *
     * The INTERFACE for this function is almost the same as that for
     * htmlspecialchars(), with the same default for quote style; however, there
     * is no 'charset' parameter. The reason for this is as follows:
     *
     * The PHP docs say:
     *      "The third argument charset defines character set used in conversion."
     *
     * I suspect PHP's htmlspecialchars() is working at the byte-value level and
     * thus _needs_ to know (or asssume) a character set because the special
     * characters to be replaced could exist at different code points in
     * different character sets. (If indeed htmlspecialchars() works at
     * byte-value level that goes some  way towards explaining why the
     * vulnerability would exist in this function, too, and not only in
     * htmlentities() which certainly is working at byte-value level.)
     *
     * This replacement function however works at character level and should
     * therefore be "immune" to character set differences - so no charset
     * parameter is needed or provided. If a third parameter is passed, it will
     * be silently ignored.
     *
     * In the OUTPUT there is a minor difference in that we use '&#39;' instead
     * of PHP's '&#039;' for a single quote: this provides compatibility with
     *      get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES)
     * (see comment by mikiwoz at yahoo dot co dot uk on
     * http://php.net/htmlspecialchars); it also matches the entity definition
     * for XML 1.0
     * (http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters).
     * Like PHP we use a numeric character reference instead of '&apos;' for the
     * single quote. For the other special characters we use the named entity
     * references, as PHP is doing.
     *
     * @author      {@link http://wikkawiki.org/JavaWoman Marjolein Katsma}
     *
     * @since       GeSHi 1.1.2a4
     * @license     http://www.gnu.org/copyleft/lgpl.html
     *              GNU Lesser General Public License
     * @copyright   Copyright 2007, {@link http://wikkawiki.org/CreditsPage
     *              Wikka Development Team}
     *
     * @access      public
     * @param       string  $string string to be converted
     * @param       integer $quote_style
     *                      - ENT_COMPAT:   escapes &, <, > and double quote (default)
     *                      - ENT_NOQUOTES: escapes only &, < and >
     *                      - ENT_QUOTES:   escapes &, <, >, double and single quotes
     * @return      string  converted string
     */
    function hsc($string, $quote_style=ENT_COMPAT)
    {
        // init
        $aTransSpecchar = array(
            '&' => '&amp;',
            '"' => '&quot;',
            '<' => '&lt;',
            '>' => '&gt;'
            );                      // ENT_COMPAT set

        if (ENT_NOQUOTES == $quote_style)       // don't convert double quotes
        {
            unset($aTransSpecchar['"']);
        }
        elseif (ENT_QUOTES == $quote_style)     // convert single quotes as well
        {
            $aTransSpecchar["'"] = '&#39;'; // (apos) htmlspecialchars() uses '&#039;'
        }

        // return translated string
        return strtr($string,$aTransSpecchar);
    }

    // }}}

    //
    // Private Methods
    //

    /**#@+
     * @access private
     */

    // {{{ _initialiseTiming()

    /**
     * Resets timing for this GeSHi object
     */
    function _initialiseTiming ()
    {
        $initial_times = array(0 => '0 0', 1 => '0 0');
        $this->_times = array(
            'pre'   => $initial_times,
            'parse' => $initial_times,
            'post'  => $initial_times
        );
    }

    // }}}
    // {{{ _parsePreProcess ()

    /**
     * Prepare the source code for parsing
     */
    function _parsePreProcess ()
    {
        // Strip newlines to common form
        $this->_source = str_replace("\r\n", "\n", $this->_source);
        $this->_source = str_replace("\r", "\n", $this->_source);

        // Get data
        // This just defines a few functions (geshi_$langname_$dialectname[_$contextname])
        $file = $this->_getLanguageDataFile();
        if (geshi_can_include($file)) {
            require_once $file;
        } else {
            $file = GESHI_LANGUAGES_ROOT . 'default/default.php';
            if (geshi_can_include($file)) {
                require_once $file;
            } else {
                // @todo [blocking 1.1.2] graceful error handling when a
                // language does not exist
                trigger_error('Language does not exist', E_USER_ERROR);
            }
        }

        // Build the context tree. This creates a new context which calls a function which may
        // define children contexts etc. etc.
        $this->_rootContext =& new GeSHiCodeContext($this->_language);


        // Load the code parser if necessary
        $language_name   = substr($this->_language, 0, strpos($this->_language, '/'));
        $codeparser_name = 'geshi' . $language_name . 'codeparser';
        if (!class_exists($codeparser_name)) {
            $codeparser_file = GESHI_LANGUAGES_ROOT . $language_name . '/'
                . "class.{$codeparser_name}.php";
            if (geshi_can_include($codeparser_file)) {
                /** Get the GeSHiCodeParser class */
                require_once GESHI_CLASSES_ROOT . 'class.geshicodeparser.php';
                /** Get the language code parser */
                require_once $codeparser_file;
            }
        }

        // Now the code parser (if existing) has been included, create it if it is defined
        if (class_exists($codeparser_name)) {
            // Get the code parser
            $codeparser =& new $codeparser_name($this->_language);
            // Call the source preprocessing method
            $this->_source = $codeparser->sourcePreProcess($this->_source);
            // Tell the styler about the code parser
            $this->_styler->setCodeParser($codeparser);
        }

        // Reset the styler parse data
        $this->_styler->resetParseData();
        // Remove contexts from the parse tree that aren't interesting
        $this->_rootContext->trimUselessChildren($this->_source);

        return true;
    }

    // }}}
    // {{{ _parsePostProcess()

    /**
     * Recieves the result string from GeSHiStyler. The result string will
     * have gone through the renderer and so be ready to use.
     *
     * This method makes sure error cases are handled, and frees any memory
     * used by the parse run
     *
     * @return The code, post-processed.
     */
    function _parsePostProcess ()
    {
        // @todo [blocking 1.1.5] (bug 5) Evaluate feasability and get working if possible the functionality below...
        //$result = preg_replace('#([^"])(((https?)|(ftp))://[a-z0-9\-]+\.([a-z0-9\-\.]+)+/?([a-zA-Z0-9\.\-_%]+/?)*\??([a-zA-Z0-9=&\[\];%]+)?(\#[a-zA-Z0-9\-_]+)?)#', '\\1<a href="\\2">\\2</a>', $result);
        //$result = preg_replace('#([a-z0-9\._\-]+@[[a-z0-9\-\.]+[a-z]+)#si', '<a href="mailto:\\1">\\1</a>', $result);
        // Destroy root context, we don't need it anymore
        $this->_rootContext = null;
        // Get code
        $code = $this->_styler->getParsedCode();
        // Trash the old GeSHiStyler
        $this->_styler =& geshi_styler(true);
        return $code;
    }

    // }}}
    // {{{ _getLanguageDataFile()

    /**
     * Helper function to convert a language name to the file name where its data will reside
     *
     * @return The absolute path of the language file where the current language data will be sourced
     * @todo only used in one place, can be removed?
     */
    function _getLanguageDataFile ()
    {
        if ('/' == '/') {
            $language_file = $this->_language . '.php';
        } else {
            $language_file = explode('/', $this->_language);
            $language_file = implode('/', $language_file) . '.php';
        }
        return GESHI_LANGUAGES_ROOT . $language_file;
    }

    // }}}
    // {{{ _clean()

    /**
     * Removes all characters other than a-z, 0-9 and / from the input
     *
     * @param  mixed $data Input to clean, can be a string or array
     * @return mixed The data in "clean" form
     */
    function _clean ($data)
    {
        return preg_replace('#[^a-z0-9/]#', '', $data);
    }

    // }}}
    // {{{ _cleanLanguageName()

    /**
     * Given a string, converts it into appropriate form for use as a
     * language name.
     *
     * @param  string $language The string to convert
     * @return string The converted language name
     */
    function _cleanLanguageName ($language)
    {
        $language = strtolower(strval($language));
        if (false === strpos($language, '/')) {
            $language .= '/' . $language;
        }
        $language = GeSHi::_clean($language);
        if (substr($language, -6) == 'common') {
            trigger_error('Cannot use "common" as a language dialect');
            $language = substr($language, 0, strpos($language, '/'));
            $language = "$language/$language";
        }
        return $language;
    }

    // }}}

    /**#@-*/

    //
    // Deprecated methods
    //

    // {{{ error()

    /**
     * From 1.2.0, this method always returns false. This method is deprecated
     * and will disappear in the next major version of GeSHi.
     *
     * @return false Always
     * @since  1.0.0
     * @deprecated
     */
    function error ()
    {
        return false;
    }

    // }}}
    // {{{ set_source()

    /**
     * Sets the source code to highlight. This method is deprecated, and will be
     * removed in 1.4/2.0.
     *
     * @param string The source code to highlight
     * @since 1.0.0
     * @deprecated In favour of {@link setSource()}
     */
    function set_source ($source)
    {
        $this->setSource($source);
    }

    // }}}
    // {{{ set_language()

    /**
     * Sets the language to use for highlighting. This method is deprecated, and
     * will be removed in the next major version of GeSHi.
     *
     * @param string The language to use for highlighting
     * @since 1.0.0
     * @deprecated In favour of {@link setLanguage()}
     */
    function set_language($language_name)
    {
        $this->setLanguage($language_name);
    }

    // }}}

}

// Reset error reporting level
error_reporting($geshi_old_reporting_level);

?>
Return current item: Pieforms