<commit_before><?php
/*
 * Copyright (C) 2014 Romain "Creak" Failliot.
 *
 * This file is part of mesamatrix.
 *
 * mesamatrix 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 3 of the License, or
 * any later version.
 *
 * mesamatrix 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libbench. If not, see <http://www.gnu.org/licenses/>.
 */

ini_set('display_errors', 1);
ini_set('error_reporting', E_ALL);
date_default_timezone_set('UTC');

function debug_print($line)
{
    print("DEBUG: ".$line."<br />\n");
}

function array_union(array $a, array $b)
{
    $res = $a;
    foreach($b as $i)
    {
        if(!in_array($i, $res))
        {
            $res[] = $i;
        }
    }

    return $res;
}

function isInDriversArray($name)
{
    global $allDrivers;

    foreach($allDrivers as $driverName)
    {
        if (strncmp($name, $driverName, strlen($driverName)) === 0)
        {
            return TRUE;
        }
    }

    return FALSE;
}

function addToHints($hint)
{
    global $allHints;

    $idx = -1;
    if(!empty($hint))
    {
        $idx = array_search($hint, $allHints);
        if($idx === FALSE)
        {
            $allHints[] = $hint;
            $idx = count($allHints) - 1;
        }
    }

    return $idx;
}

class OglSupportedDriver
{
    public function __construct($name)
    {
        global $allDrivers;

        $this->name = "<undefined>";
        $this->hintIdx = -1;
        foreach($allDrivers as $driver)
        {
            $driverLen = strlen($driver);
            if(strncmp($name, $driver, $driverLen) === 0)
            {
                $this->name = $driver;
                $this->setHint(substr($name, $driverLen + 1));
            }
        }
    }

    public function setName($name) { $this->name = $name; }
    public function getName()      { return $this->name; }

    public function setHint($hint) { $this->hintIdx = addToHints($hint); }
    public function getHintIdx()   { return $this->hintIdx; }

    private $name;
    private $hintIdx;
};

class OglExtension
{
    public function __construct($name, $status, $supportedDrivers = array())
    {
        global $allDrivers;

        $this->name = $name;
        $this->status = $status;

        // Set the hint.
        $hint = "";
        if(strncmp($status, "DONE", strlen("DONE")) === 0)
        {
            $hint = substr($status, strlen("DONE") + 1);
        }
        else if(strncmp($status, "not started", strlen("not started")) === 0)
        {
            $hint = substr($status, strlen("not started") + 1);
        }
        else
        {
            $hint = $status;
        }

        $this->setHint($hint);

        // Set the supported drivers list.
        $this->supportedDrivers = array();
        foreach($supportedDrivers as &$driverName)
        {
            $this->supportedDrivers[] = new OglSupportedDriver($driverName);
        }
    }

    public function setName($name) { $this->name = $name; }
    public function getName()      { return $this->name; }

    public function setStatus($status) { $this->status = $status; }
    public function getStatus()        { return $this->status; }

    public function setHint($hint) { $this->hintIdx = addToHints($hint); }
    public function getHintIdx()   { return $this->hintIdx; }

    public function addSupportedDriver($supportedDriver) { $this->supportedDrivers[] = $supportedDriver; }
    public function getSupportedDrivers()                { return $this->supportedDrivers; }

    private $name;
    private $status;
    private $hintIdx;
    private $supportedDrivers;
};

class OglVersion
{
    public function __construct($glName, $glVersion, $glslName, $glslVersion)
    {
        $this->glName = $glName;
        $this->glVersion = $glVersion;
        $this->glslName = $glslName;
        $this->glslVersion = $glslVersion;
        $this->extensions = array();
    }

    /// GL name and version.
    public function setGlName($name)       { $this->glName = $name; }
    public function getGlName()            { return $this->glName; }
    public function setGlVersion($version) { $this->glVersion = $version; }
    public function getGlVersion()         { return $this->glVersion; }

    /// GLSL name and version.
    public function setGlslName($name)       { $this->glslName = $name; }
    public function getGlslName()            { return $this->glslName; }
    public function setGlslVersion($version) { $this->glslVersion = $version; }
    public function getGlslVersion()         { return $this->glslVersion; }

    /// GL/GLSL extensions.
    public function addExtension($name, $status, $supportedDrivers = array())
    {
        $this->extensions[] = new OglExtension($name, $status, $supportedDrivers);
    }

    public function getExtensions() { return $this->extensions; }

    private $glName;
    private $glVersion;
    private $glslName;
    private $glslVersion;
    private $extensions;
};

class OglMatrix
{
    public function __construct()
    {
        $this->glVersions = array();
    }

    public function addGlVersion($glVersion)
    {
        array_push($this->glVersions, $glVersion);
    }

    public function getGlVersions()
    {
        return $this->glVersions;
    }

    private $glVersions;
};

function skipEmptyLines($curLine, $handle)
{
    while($curLine !== FALSE && $curLine === "\n")
    {
        $curLine = fgets($handle);
    }

    return $curLine;
}

$allDrivers = array(
    "softpipe",
    "swrast",
    "llvmpipe",
    "i965",
    "nv50",
    "nvc0",
    "r300",
    "r600",
    "radeonsi");
$allHints = array();

$gl3Filename = "GL3.txt";
$gl3PlainUrl = "http://cgit.freedesktop.org/mesa/mesa/plain/docs/GL3.txt";
$gl3TreeUrl = "http://cgit.freedesktop.org/mesa/mesa/tree/docs/GL3.txt";
$gl3LogUrl = "http://cgit.freedesktop.org/mesa/mesa/log/docs/GL3.txt";
$lastUpdate = 0;

$getLatestFileVersion = TRUE;
if(file_exists($gl3Filename))
{
    $mtime = filemtime($gl3Filename);
    if($mtime + 3600 > time())
    {
        $getLatestFileVersion = FALSE;
        $lastUpdate = $mtime;
    }
}

if($getLatestFileVersion)
{
    $distantContent = file_get_contents($gl3PlainUrl);
    if($distantContent !== FALSE)
    {
        $cacheHandle = fopen($gl3Filename, "w");
        if($cacheHandle !== FALSE)
        {
            fwrite($cacheHandle, $distantContent);
            fclose($cacheHandle);
            $lastUpdate = time();
        }

        unset($distantContent);
    }
}

// Parse the text file.
$handle = fopen($gl3Filename, "r")
    or exit("Can't read \"${gl3Filename}\"");

$reTableHeader = "/^Feature([ ]+)Status/";
$reVersion = "/^(GL(ES)?) ?([[:digit:]]+\.[[:digit:]]+), (GLSL( ES)?) ([[:digit:]]+\.[[:digit:]]+)/";
$reAllDone = "/ --- all DONE: (.*)/";
$reExtension = "/^[^.]+$/";
$reNote = "/^(\(.+\)) (.*)$/";

$ignoreHints = array("all drivers");
$oglMatrix = new OglMatrix();

$line = fgets($handle);
while($line !== FALSE)
{
    if(preg_match($reTableHeader, $line, $matches) === 1)
    {
        // Should be $lineWidth-2, but the file has a variable length in column 1
        $lineWidth = strlen("Feature") + strlen($matches[1]);
        $reExtension = "/^  (.{1,".$lineWidth."})[ ]+([^\(]+)(\((.*)\))?$/";
        $line = fgets($handle);
        continue;
    }

    if(preg_match($reVersion, $line, $matches) === 1)
    {
        $glVersion = new OglVersion($matches[1], $matches[3], $matches[4], $matches[6]);

        $allSupportedDrivers = array();
        if(preg_match($reAllDone, $line, $matches) === 1)
        {
            $allSupportedDrivers = array_union($allSupportedDrivers, explode(", ", $matches[1]));
        }

        $line = skipEmptyLines(fgets($handle), $handle);

        $parentDrivers = NULL;
        while($line !== FALSE && $line !== "\n")
        {
            if(preg_match($reExtension, $line, $matches) === 1)
            {
                $supportedDrivers = $allSupportedDrivers;
                $matches[1] = trim($matches[1]);
                if($matches[1][0] === "-")
                {
                    $supportedDrivers = array_union($supportedDrivers, $parentDrivers);
                }

                $matches[2] = trim($matches[2]);
                $isDone = strncmp($matches[2], "DONE", strlen("DONE")) === 0;
                if($isDone && !isset($matches[3]))
                {
                    $supportedDrivers = array_union($supportedDrivers, $allDrivers);
                }
                else if($isDone && isset($matches[4]))
                {
                    $driverFound = FALSE;
                    $driversList = explode(", ", $matches[4]);
                    foreach($driversList as $currentDriver)
                    {
                        if(isInDriversArray($currentDriver))
                        {
                            $supportedDrivers[] = $currentDriver;
                            $driverFound = TRUE;
                        }
                    }
                    if (!$driverFound && !empty($matches[4]))
                    {
                        if (!in_array($matches[4], $ignoreHints))
                        {
                            $matches[2] = $matches[2]." ".$matches[4]."";
                        }
                        $supportedDrivers = array_union($supportedDrivers, $allDrivers);
                    }
                }
                else if (isset($matches[4]) && !empty($matches[4]))
                {
                    $matches[2] = $matches[2]." (".$matches[4].")";
                }

                if($matches[1][0] !== "-")
                {
                    $parentDrivers = $supportedDrivers;
                }

                $glVersion->addExtension($matches[1], $matches[2], $supportedDrivers);
            }

            $line = fgets($handle);
        }

        $oglMatrix->addGlVersion($glVersion);

        $line = skipEmptyLines($line, $handle);

        while($line !== FALSE && preg_match($reNote, $line, $matches) === 1)
        {
            $idx = array_search($matches[1], $allHints);
            if($idx !== FALSE)
            {
                $allHints[$idx] = $matches[2];
            }

            $line = fgets($handle);
        }
    }
    else
    {
        $line = fgets($handle);
    }
}

fclose($handle);

// Write the HTML file now.
?>
<!DOCTYPE html>
<html>
    <head>
        <title>The OpenGL vs Mesa matrix</title><commit_msg>Put the parser in an object.<commit_after><?php
/*
 * Copyright (C) 2014 <NAME>" Failliot.
 *
 * This file is part of mesamatrix.
 *
 * mesamatrix 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 3 of the License, or
 * any later version.
 *
 * mesamatrix 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libbench. If not, see <http://www.gnu.org/licenses/>.
 */

ini_set('display_errors', 1);
ini_set('error_reporting', E_ALL);
date_default_timezone_set('UTC');

function debug_print($line)
{
    print("DEBUG: ".$line."<br />\n");
}

// List of all the drivers.
$allDrivers = array(
    "softpipe",
    "swrast",
    "llvmpipe",
    "i965",
    "nv50",
    "nvc0",
    "r300",
    "r600",
    "radeonsi");

function array_union(array $a, array $b)
{
    $res = $a;
    foreach($b as $i)
    {
        if(!in_array($i, $res))
        {
            $res[] = $i;
        }
    }

    return $res;
}

class OglSupportedDriver
{
    public function __construct($name)
    {
        global $allDrivers;

        $this->name = "<undefined>";
        $this->hintIdx = -1;
        foreach($allDrivers as $driver)
        {
            $driverLen = strlen($driver);
            if(strncmp($name, $driver, $driverLen) === 0)
            {
                $this->name = $driver;
                $this->setHint(substr($name, $driverLen + 1));
            }
        }
    }

    public function setName($name) { $this->name = $name; }
    public function getName()      { return $this->name; }

    public function setHint($hint) { $this->hintIdx = addToHints($hint); }
    public function getHintIdx()   { return $this->hintIdx; }

    private $name;
    private $hintIdx;
};

class OglExtension
{
    public function __construct($name, $status, $supportedDrivers = array())
    {
        global $allDrivers;

        $this->name = $name;
        $this->status = $status;

        // Set the hint.
        $hint = "";
        if(strncmp($status, "DONE", strlen("DONE")) === 0)
        {
            $hint = substr($status, strlen("DONE") + 1);
        }
        else if(strncmp($status, "not started", strlen("not started")) === 0)
        {
            $hint = substr($status, strlen("not started") + 1);
        }
        else
        {
            $hint = $status;
        }

        $this->setHint($hint);

        // Set the supported drivers list.
        $this->supportedDrivers = array();
        foreach($supportedDrivers as &$driverName)
        {
            $this->supportedDrivers[] = new OglSupportedDriver($driverName);
        }
    }

    public function setName($name) { $this->name = $name; }
    public function getName()      { return $this->name; }

    public function setStatus($status) { $this->status = $status; }
    public function getStatus()        { return $this->status; }

    public function setHint($hint) { $this->hintIdx = addToHints($hint); }
    public function getHintIdx()   { return $this->hintIdx; }

    public function addSupportedDriver($supportedDriver) { $this->supportedDrivers[] = $supportedDriver; }
    public function getSupportedDrivers()                { return $this->supportedDrivers; }

    private $name;
    private $status;
    private $hintIdx;
    private $supportedDrivers;
};

class OglVersion
{
    public function __construct($glName, $glVersion, $glslName, $glslVersion)
    {
        $this->glName = $glName;
        $this->glVersion = $glVersion;
        $this->glslName = $glslName;
        $this->glslVersion = $glslVersion;
        $this->extensions = array();
    }

    /// GL name and version.
    public function setGlName($name)       { $this->glName = $name; }
    public function getGlName()            { return $this->glName; }
    public function setGlVersion($version) { $this->glVersion = $version; }
    public function getGlVersion()         { return $this->glVersion; }

    /// GLSL name and version.
    public function setGlslName($name)       { $this->glslName = $name; }
    public function getGlslName()            { return $this->glslName; }
    public function setGlslVersion($version) { $this->glslVersion = $version; }
    public function getGlslVersion()         { return $this->glslVersion; }

    /// GL/GLSL extensions.
    public function addExtension($name, $status, $supportedDrivers = array())
    {
        $this->extensions[] = new OglExtension($name, $status, $supportedDrivers);
    }

    public function getExtensions() { return $this->extensions; }

    private $glName;
    private $glVersion;
    private $glslName;
    private $glslVersion;
    private $extensions;
};

class OglMatrix
{
    public function __construct()
    {
        $this->glVersions = array();
    }

    public function addGlVersion($glVersion)
    {
        array_push($this->glVersions, $glVersion);
    }

    public function getGlVersions()
    {
        return $this->glVersions;
    }

    private $glVersions;
};

class OglParser
{
    public function parse($filename)
    {
        global $allDrivers, $allHints;

        $handle = fopen($filename, "r");
        if($handle === FALSE)
        {
            return null;
        }

        // Regexp patterns.
        $reTableHeader = "/^Feature([ ]+)Status/";
        $reVersion = "/^(GL(ES)?) ?([[:digit:]]+\.[[:digit:]]+), (GLSL( ES)?) ([[:digit:]]+\.[[:digit:]]+)/";
        $reAllDone = "/ --- all DONE: (.*)/";
        $reExtension = "/^[^.]+$/";
        $reNote = "/^(\(.+\)) (.*)$/";

        $ignoreHints = array("all drivers");
        $oglMatrix = new OglMatrix();

        $line = fgets($handle);
        while($line !== FALSE)
        {
            if(preg_match($reTableHeader, $line, $matches) === 1)
            {
                // Should be $lineWidth-2, but the file has a variable length in column 1
                $lineWidth = strlen("Feature") + strlen($matches[1]);
                $reExtension = "/^  (.{1,".$lineWidth."})[ ]+([^\(]+)(\((.*)\))?$/";
                $line = fgets($handle);
                continue;
            }

            if(preg_match($reVersion, $line, $matches) === 1)
            {
                $glVersion = new OglVersion($matches[1], $matches[3], $matches[4], $matches[6]);

                $allSupportedDrivers = array();
                if(preg_match($reAllDone, $line, $matches) === 1)
                {
                    $allSupportedDrivers = array_union($allSupportedDrivers, explode(", ", $matches[1]));
                }

                $line = $this->skipEmptyLines(fgets($handle), $handle);

                $parentDrivers = NULL;
                while($line !== FALSE && $line !== "\n")
                {
                    if(preg_match($reExtension, $line, $matches) === 1)
                    {
                        $supportedDrivers = $allSupportedDrivers;
                        $matches[1] = trim($matches[1]);
                        if($matches[1][0] === "-")
                        {
                            $supportedDrivers = array_union($supportedDrivers, $parentDrivers);
                        }

                        $matches[2] = trim($matches[2]);
                        $isDone = strncmp($matches[2], "DONE", strlen("DONE")) === 0;
                        if($isDone && !isset($matches[3]))
                        {
                            $supportedDrivers = array_union($supportedDrivers, $allDrivers);
                        }
                        else if($isDone && isset($matches[4]))
                        {
                            $driverFound = FALSE;
                            $driversList = explode(", ", $matches[4]);
                            foreach($driversList as $currentDriver)
                            {
                                if($this->isInDriversArray($currentDriver))
                                {
                                    $supportedDrivers[] = $currentDriver;
                                    $driverFound = TRUE;
                                }
                            }
                            if (!$driverFound && !empty($matches[4]))
                            {
                                if (!in_array($matches[4], $ignoreHints))
                                {
                                    $matches[2] = $matches[2]." ".$matches[4]."";
                                }
                                $supportedDrivers = array_union($supportedDrivers, $allDrivers);
                            }
                        }
                        else if (isset($matches[4]) && !empty($matches[4]))
                        {
                            $matches[2] = $matches[2]." (".$matches[4].")";
                        }

                        if($matches[1][0] !== "-")
                        {
                            $parentDrivers = $supportedDrivers;
                        }

                        $glVersion->addExtension($matches[1], $matches[2], $supportedDrivers);
                    }

                    $line = fgets($handle);
                }

                $oglMatrix->addGlVersion($glVersion);

                $line = $this->skipEmptyLines($line, $handle);

                while($line !== FALSE && preg_match($reNote, $line, $matches) === 1)
                {
                    $idx = array_search($matches[1], $allHints);
                    if($idx !== FALSE)
                    {
                        $allHints[$idx] = $matches[2];
                    }

                    $line = fgets($handle);
                }
            }
            else
            {
                $line = fgets($handle);
            }
        }

        fclose($handle);

        return $oglMatrix;
    }

    private function skipEmptyLines($curLine, $handle)
    {
        while($curLine !== FALSE && $curLine === "\n")
        {
            $curLine = fgets($handle);
        }

        return $curLine;
    }

    private function isInDriversArray($name)
    {
        global $allDrivers;

        foreach($allDrivers as $driverName)
        {
            if (strncmp($name, $driverName, strlen($driverName)) === 0)
            {
                return TRUE;
            }
        }

        return FALSE;
    }
};

// Hints gathered during the parsing.
$allHints = array();
function addToHints($hint)
{
    global $allHints;

    $idx = -1;
    if(!empty($hint))
    {
        $idx = array_search($hint, $allHints);
        if($idx === FALSE)
        {
            $allHints[] = $hint;
            $idx = count($allHints) - 1;
        }
    }

    return $idx;
}

$gl3Filename = "GL3.txt";
$gl3PlainUrl = "http://cgit.freedesktop.org/mesa/mesa/plain/docs/GL3.txt";
$lastUpdate = 0;

$getLatestFileVersion = TRUE;
if(file_exists($gl3Filename))
{
    $mtime = filemtime($gl3Filename);
    if($mtime + 3600 > time())
    {
        $getLatestFileVersion = FALSE;
        $lastUpdate = $mtime;
    }
}

if($getLatestFileVersion)
{
    $distantContent = file_get_contents($gl3PlainUrl);
    if($distantContent !== FALSE)
    {
        $cacheHandle = fopen($gl3Filename, "w");
        if($cacheHandle !== FALSE)
        {
            fwrite($cacheHandle, $distantContent);
            fclose($cacheHandle);
            $lastUpdate = time();
        }

        unset($distantContent);
    }
}

// Parse the local file.
$parser = new OglParser();
$oglMatrix = $parser->parse($gl3Filename);
if(!$oglMatrix)
{
    exit("Can't read \"${gl3Filename}\"");
}

$gl3TreeUrl = "http://cgit.freedesktop.org/mesa/mesa/tree/docs/GL3.txt";
$gl3LogUrl = "http://cgit.freedesktop.org/mesa/mesa/log/docs/GL3.txt";

// Write the HTML code.
?>
<!DOCTYPE html>
<html>
    <head>
        <title>The OpenGL vs Mesa matrix</title>
{'fraction_non_alphanumeric': 0.15110683349374399, 'fraction_numerical': 0.007699711260827719, 'mean_word_length': 1.851315953598603, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 110, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1106798', 'n_tokens_mistral': 7050, 'n_tokens_neox': 6646, 'n_words': 1411}