*/
if (!defined("DOKU_PLUGIN")) define("DOKU_PLUGIN", DOKU_INC."lib/plugins/");
require_once(DOKU_PLUGIN . "syntax.php");
require_once(DOKU_PLUGIN . "register/register.php");
class syntax_plugin_register extends DokuWiki_Syntax_Plugin
{
public function getInfo()
{
return confToHash(dirname(__FILE__).'/info.txt');
}
public function getType() { return "protected"; }
public function getSort() { return 333; }
public function connectTo($mode)
{
$this->Lexer->addEntryPattern("", $mode, "plugin_register");
}
public function postConnect()
{
/*
$keywords = array(
"register", "long desc", "short desc", "perms", "addr", "reset",
"length", "bit range", "bit name", "bit desc", "bit flags"
);
foreach ($keywords as $k)
$this->Lexer->addPattern("$k = ", "plugin_register");
*/
$this->Lexer->addExitPattern("", "plugin_register");
}
public function handle($match, $state, $pos, &$handler)
{
switch ($state) {
/*1*/case DOKU_LEXER_ENTER: return array($state, $match);
/*2*/case DOKU_LEXER_MATCHED: return array();
/*3*/case DOKU_LEXER_UNMATCHED: return array($state, $match);
/*4*/case DOKU_LEXER_EXIT: return array($state, $match);
/*5*/case DOKU_LEXER_SPECIAL: return array();
}
return false;
}
/* XXX: remember, php error will not flush renderer and thus no debug messages */
private $debug = 0;
private function _msg(&$renderer, $type, $msg)
{
$bt = debug_backtrace();
$renderer->doc .= "
{register plugin $type}:".$bt[2]["function"]."():".$bt[1]["line"].": $msg
";
unset($bt);
}
private function err(&$renderer, $msg) { $this->_msg($renderer, "error", $msg); }
private function dbg(&$renderer, $msg) { if ($this->debug) $this->_msg($renderer, "debug", $msg); }
private function get_output_pieces(&$renderer, $match)
{
global $conf;
$dir = $conf["mediadir"] . "/register";
$hash = md5(serialize($match));
$file = "$dir/$hash.png";
$url = DOKU_BASE . "lib/exe/fetch.php?cache=$cache&media=" . urlencode("register:$hash.png");
if (!io_mkdir_p($dir)) {
$this->err($renderer, "failed to create output dir '$dir'");
return false;
}
return array($file, $url);
}
private function push_bit(&$bits, &$bit)
{
if (!array_key_exists("name", $bit))
$bit["name"] = "ERROR:UNDEF";
if (!array_key_exists("desc", $bit))
$bit["desc"] = "";
if (!array_key_exists("flags", $bit))
$bit["flags"] = "";
$range = explode(" ", $bit["range"]);
if (count($range) == 1)
$range[1] = $range[0];
array_push($bits, array($range[0], $range[1], $bit["name"], $bit["desc"], $bit["flags"]));
$bit = array();
}
private function parse_match(&$renderer, $match)
{
$keys = array();
$bits = array();
$bit = array();
$lines = explode("\n", $match);
foreach ($lines as $l) {
if ($l == "")
continue;
$this->dbg($renderer, "line: $l");
$val = strstr($l, " = ");
$key = substr($l, 0, strlen($l) - strlen($val));
$val = str_replace("\\n", "\n", substr($val, 3));
if ($key == "xml")
return $this->parse_match_xml($renderer, $match);
if (substr($key, 0, 4) == "bit ") {
$subkey = substr($key, 4);
if ($subkey == "range" && count($bit) > 0)
$this->push_bit($bits, $bit);
$bit[$subkey] = $val;
$this->dbg($renderer, "BIT[$subkey] = $val");
} else {
$keys[$key] = $val;
$this->dbg($renderer, "KEY[$key] = $val");
}
}
if (count($bit) > 0)
$this->push_bit($bits, $bit);
if (!array_key_exists("long desc", $keys))
$keys["long desc"] = "";
if (!array_key_exists("addr", $keys))
$keys["addr"] = "";
if (!array_key_exists("reset", $keys))
$keys["reset"] = "undef";
if (!array_key_exists("perms", $keys))
$keys["perms"] = "";
if (!array_key_exists("short desc", $keys))
$keys["short desc"] = "";
return array($keys, $bits);
}
private function parse_match_xml(&$renderer, $match)
{
$xml_path = DOKU_PLUGIN . "register/xml/";
$lines = explode("\n", $match);
foreach ($lines as $l) {
$val = strstr($l, " = ");
$key = substr($l, 0, strlen($l) - strlen($val));
$val = str_replace("\\n", "\n", substr($val, 3));
$keys[$key] = $val;
}
if (eregi_replace("[-.a-z0-9]*", "", $keys["xml"]) != "") {
$this->err($renderer, "invalid xml file name '".$keys["xml"]."'");
return false;
}
$keys["xml"] .= (substr($keys["xml"], -4) == ".xml" ? "" : ".xml");
if (file_exists($xml_path . "ADSP-" . $keys["xml"]))
$keys["xml"] = "ADSP-" . $keys["xml"];
$xml = $xml_path . $keys["xml"];
$this->dbg($renderer, "XML = $xml");
$fp = fopen($xml, "r");
if (!$fp) {
$this->err($renderer, "unable to read xml file '$xml'");
return false;
}
global $adi_xml_search, $adi_xml_state, $adi_xml_result;
$adi_xml_search = $keys["register"];
$adi_xml_state = 1;
$adi_xml_result = array();
$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "adi_register_xml_parse", "");
while (($data = fread($fp, 8192)) && $adi_xml_state) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
$this->err($renderer, "XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser));
}
}
xml_parser_free($xml_parser);
fclose($fp);
$attrs = $adi_xml_result["attrs"];
$keys["long desc"] = $attrs["DESCRIPTION"];
$keys["short desc"] = $attrs["DEF-COMMENT"]; /*DEF-HEADER*/
$keys["addr"] = $attrs["WRITE-ADDRESS"];
$keys["length"] = $attrs["BIT-SIZE"];
$keys["reset"] = "undef";
$bits = array_reverse($adi_xml_result["bits"]);
return array($keys, $bits);
}
private function generate_image(&$renderer, $match, $file)
{
/* if the output file exists, nothing for us to do */
if (is_readable($file))
return true;
$ret = $this->parse_match($renderer, $match);
if (!$ret)
return false;
list($keys, $bits) = $ret;
/*
register = WDOG_CTL
long desc = Watchdog Control Register
short desc = moo
perms = RW
addr = 0xFFC00200
reset = 0x0AD0
length = 16
bit range = 15 15
bit name = WDR0
bit desc = 0 - Watchdog timer has not expired\n1 - Watchdog timer has expired
bit flags = W1C
bit range = 11 4
bit name = WDEN
bit desc = 0xAD - Counter disabled\nAll other values - Counter enabled
*/
$reg = new register(
$keys["register"], $keys["long desc"], $keys["addr"], $keys["reset"],
$keys["length"], $keys["perms"], $keys["short desc"],
$bits
);
if (!$reg->render($file))
return false;
unset($reg);
/* pass the WDOG_CTL back up for "alt" in ? */
//return array($keys["register"], $keys["long desc"]);
return true;
}
public function render($mode, &$renderer, $data)
{
if ($mode != "xhtml")
return false;
/* convert the stuff returned from handle() */
if (gettype($data) != "array") {
$this->err($renderer, "incoming data from handle() is not an array");
return false;
}
list($state, $match) = $data;
$this->dbg($renderer, "state: $state match: $match");
if ($state != DOKU_LEXER_UNMATCHED)
return true; /* nothing to do */
/* setup the file / url locations */
$pieces = $this->get_output_pieces($renderer, $match);
if ($pieces == false) {
$this->err($renderer, "get_output_pieces() failed");
return false;
}
list($file, $url) = $pieces;
/* generate the image */
if (!$this->generate_image($renderer, $match, $file)) {
$this->err($renderer, "generate_image() failed");
return false;
}
/* present the image! */
$renderer->doc .= "";
return true;
}
}
function adi_register_xml_parse($parser, $name, $attrs)
{
global $adi_xml_search, $adi_xml_state, $adi_xml_result;
if ($name != "REGISTER")
return false;
switch ($adi_xml_state) {
case 1:
if ($attrs["NAME"] == $adi_xml_search) {
$adi_xml_result["attrs"] = $attrs;
$adi_xml_result["bits"] = array();
$adi_xml_state = 2;
}
break;
case 2:
if ($attrs["PARENT"] != $adi_xml_search) {
$adi_xml_state = 0;
return false;
}
$adi_xml_result["bits"][$attrs["BIT-POSITION"]] = array(
$attrs["BIT-POSITION"] - 1 + $attrs["BIT-SIZE"],
$attrs["BIT-POSITION"],
$attrs["NAME"],
$attrs["DESCRIPTION"],
""
);
break;
}
}
?>