summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2008-10-06 22:19:54 +0000
committerMaurus Cuelenaere <mcuelenaere@gmail.com>2008-10-06 22:19:54 +0000
commit20fb47ec778abe215ca69692434ff753596319e6 (patch)
tree69665298c0f58c07a1aa9677d33ad395ad9ccd13 /utils
parent34148b9a2173b0bd80b4acd18d23216ae54cb865 (diff)
downloadrockbox-20fb47ec778abe215ca69692434ff753596319e6.tar.gz
rockbox-20fb47ec778abe215ca69692434ff753596319e6.tar.bz2
rockbox-20fb47ec778abe215ca69692434ff753596319e6.zip
Commit FS#9462: an semi-automatic plugin API documentation generator
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18722 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils')
-rw-r--r--utils/rockbox_api/README29
-rwxr-xr-xutils/rockbox_api/functions.php337
-rwxr-xr-xutils/rockbox_api/gen_html.php110
-rwxr-xr-xutils/rockbox_api/generate.php63
-rw-r--r--utils/rockbox_api/layout.css108
-rwxr-xr-xutils/rockbox_api/update.php119
6 files changed, 766 insertions, 0 deletions
diff --git a/utils/rockbox_api/README b/utils/rockbox_api/README
new file mode 100644
index 0000000000..1ed251c918
--- /dev/null
+++ b/utils/rockbox_api/README
@@ -0,0 +1,29 @@
+==============================
+generate.php
+==============================
+
+ php generate.php > output.txt
+
+--------------
+ Generates output.txt of apps/plugin.h
+
+==============================
+update.php
+==============================
+
+ php update.php input_file.txt > output.txt
+
+--------------
+ Updates input_file.txt with newer values of apps/plugin.h
+
+==============================
+gen_html.php
+==============================
+
+ php gen_html.php input_file.txt
+
+--------------
+ Generates HTML output of input_file.txt in output/*.html
+
+ Known issues:
+ * [F[function]] doesn't work with functions outside of the current .html \ No newline at end of file
diff --git a/utils/rockbox_api/functions.php b/utils/rockbox_api/functions.php
new file mode 100755
index 0000000000..0f34fc69e0
--- /dev/null
+++ b/utils/rockbox_api/functions.php
@@ -0,0 +1,337 @@
+<?
+$svn = "http://svn.rockbox.org/viewvc.cgi/trunk/";
+$wiki = "http://www.rockbox.org/wiki/";
+
+function func_sort($a, $b)
+{
+ $a = preg_replace('/^((unsigned|const|struct|enum) [^ ]*|[a-z0-9 \*_]*) [\*]?/i', '', $a);
+ $b = preg_replace('/^((unsigned|const|struct|enum) [^ ]*|[a-z0-9 \*_]*) [\*]?/i', '', $b);
+ return strnatcasecmp($a, $b);
+}
+
+function get_newest()
+{
+ global $svn;
+
+ $text = file_get_contents("../../apps/plugin.h");
+
+ $text = str_replace(array("\r\n", "\r"), "\n", $text);
+
+ /* Located plugin_api struct */
+ foreach(explode("\n", $text) as $line_nr => $line)
+ {
+ if(trim($line) == "struct plugin_api {")
+ {
+ $text = explode("\n", $text);
+ $text = array_slice($text, $line_nr+1);
+ break;
+ }
+ }
+
+ foreach($text as $line_nr => $line)
+ {
+ if(trim($line) == "};")
+ {
+ $text = array_slice($text, 0, $line_nr-1);
+ break;
+ }
+ }
+ /* Locating done */
+
+ /* Clean up stuff a bit .. */
+ for($i=0; $i<count($text); $i++)
+ $text[$i] = trim($text[$i]);
+
+
+ /* Fake preprocesser */
+ $ret = array();
+ $_groups = array();
+ $conditions = array();
+ $strip_next = 0;
+ $group = "";
+ for($i=0; $i<count($text); $i++)
+ {
+ $tmp = trim($text[$i]);
+
+ if(substr($tmp, 0, 1) == '#')
+ {
+ $tmp = trim(substr($tmp, 1));
+ if(strtolower(substr($tmp, 0, 2)) == "if")
+ {
+ if(strtolower(substr($tmp, 2, 3)) == "def")
+ $conditions[] = "defined(".substr($tmp, 6).")";
+ else if(strtolower(substr($tmp, 2, 4)) == "ndef")
+ $conditions[] = "!defined(".substr($tmp, 7).")";
+ else
+ {
+ while(substr($tmp, strlen($tmp)-1, 1) == "\\")
+ {
+ $i++;
+ $tmp = substr($tmp, 0, strlen($tmp)-1)." ".trim($text[$i]);
+ }
+
+ $conditions[] = substr($tmp, 3);
+ }
+ }
+ else if(strtolower(substr($tmp, 0, 4)) == "elif")
+ {
+ while(substr($tmp, strlen($tmp)-1, 1) == "\\")
+ {
+ $i++;
+ $tmp = substr($tmp, 0, strlen($tmp)-1)." ".trim($text[$i]);
+ }
+ $conditions[count($conditions)-1] = substr($tmp, 5);
+ }
+ else if(strtolower(substr($tmp, 0, 4)) == "else")
+ $conditions[count($conditions)-1] = "!( ".$conditions[count($conditions)-1]." )";
+ else if(strtolower(substr($tmp, 0, 5)) == "endif")
+ array_pop($conditions);
+ }
+ else if(strlen($tmp) == 0)
+ $group = "";
+ else if(substr($tmp, 0, 2) == "/*")
+ {
+ while(strpos($tmp, "*/") === false)
+ {
+ $i++;
+ $tmp .= " ".trim($text[$i]);
+ }
+ $group = explode("/*", trim($tmp));
+ $group = explode("*/", $group[1]);
+ $group = trim($group[0]);
+ }
+ else
+ {
+ while(strpos($tmp, ";") === false)
+ {
+ $i++;
+ $tmp .= " ".trim($text[$i]);
+ }
+
+ /* Replace those (*func)(int args) with func(int args) */
+ $tmp = preg_replace('/\(\*([^\)]*)\)/i', '\1', $tmp, 1);
+ $tmp = substr($tmp, 0, strlen($tmp)-1);
+ $ret[$tmp] = array("func" => $tmp, "cond" => "(".implode(") && (", $conditions).")", "group" => $group);
+ }
+ }
+
+ uksort($ret, "func_sort");
+
+ return $ret;
+}
+
+function parse_documentation($data)
+{
+ $data = explode("\n", $data);
+
+ $ret = array();
+ $cur_func = "";
+ foreach($data as $line)
+ {
+ if(substr($line, 0, 1) == "#")
+ continue;
+ else if(substr($line, 0, 4) == " ")
+ {
+ $tmp = trim($line);
+ if(strpos($tmp, " ") !== false)
+ $tmp = array(substr($tmp, 1, strpos($tmp, " ")-1), substr($tmp, strpos($tmp, " ")) );
+ else
+ $tmp = array(substr($tmp, 1), "");
+
+ $ret[$cur_func][$tmp[0]][] = $tmp[1];
+ }
+ else if(strlen($line) == 0)
+ continue;
+ else
+ $cur_func = substr($line, 0);
+ }
+
+ $_ret = array();
+ foreach($ret as $func => $el)
+ {
+ if(isset($el["group"]))
+ $group = trim($el["group"][0]);
+ else
+ $group = "misc";
+
+ $_ret[$group][$func] = $el;
+ }
+
+ return $_ret;
+}
+
+function get_func($func)
+{
+ $func = preg_replace('/^((unsigned|const|struct|enum) [^ ]*|[a-z0-9 \*_]*) [\*]?/i', '', $func);
+ if(strpos($func, "PREFIX") !== false)
+ $func = substr($func, 0, strrpos($func, "("));
+ else if(strpos($func, "(") !== false)
+ $func = substr($func, 0, strpos($func, "("));
+
+ return $func;
+}
+
+function get_args($func)
+{
+ /* Check if this _is_ a function */
+ if(strpos($func, "(") === false)
+ return array();
+
+ /* Get rid of return value */
+ $func = preg_replace('/^((unsigned|const|struct|enum) [^ ]*|[a-z0-9 \*_]*) [\*]?/i', '', $func);
+
+ /* Get rid of function name */
+ if(strpos($func, "(") !== false)
+ $func = substr($func, strpos($func, "("));
+
+ /* Get rid of ATTRIBUTE_PRINTF */
+ if(strpos($func, "ATTRIBUTE_PRINTF") !== false)
+ $func = substr($func, 0, strpos($func, "ATTRIBUTE_PRINTF"));
+
+ $level = 0;
+ $args = array();
+ $buffer = "";
+ for($i=0; $i<strlen($func); $i++)
+ {
+ switch($func{$i})
+ {
+ case "(":
+ $level++;
+ if($level > 1)
+ $buffer .= "(";
+ break;
+ case ")":
+ $level--;
+ if($level > 0)
+ {
+ $buffer .= ")";
+ break;
+ }
+ case ",":
+ if($level <= 1)
+ {
+ if(strpos($buffer, "(,") !== false)
+ {
+ $tmp = array();
+ preg_match_all('/[^ ]*, [^)]*\)/', $buffer, $tmp);
+ $tmp = $tmp[0];
+ foreach($tmp as $el)
+ {
+ if(strlen($el) > 0)
+ $args[] = trim($el);
+ }
+ $tmp = preg_replace('/[^ ]*, [^)]*\)/', '', $buffer);
+ $args[] = trim($tmp);
+ }
+ else
+ $args[] = trim($buffer);
+ $buffer = "";
+ }
+ else
+ $buffer .= ",";
+ break;
+ default:
+ $buffer .= $func{$i};
+ break;
+ }
+ }
+
+ /* Filter out void */
+ for($i=0; $i<count($args); $i++)
+ {
+ if($args[$i] == "void")
+ unset($args[$i]);
+ }
+
+ return $args;
+}
+
+function get_return($func)
+{
+ $ret = array();
+ preg_match('/^((unsigned|const|struct|enum) [^ ]*|[a-z0-9 \*_]*) [\*]?/i', $func, $ret);
+
+ if(trim($ret[0]) == "void")
+ return false;
+ else
+ return trim($ret[0]);
+}
+
+function split_var($var)
+{
+ if(strpos($var, "(,") !== false)
+ {
+ $p1 = substr($var, 0, strrpos($var, " "));
+ $p2 = substr($var, strrpos($var, " "));
+ $p2 = substr($p2, 0, strlen($p2)-1);
+ }
+ else if(strpos($var, "(*") !== false)
+ {
+ $p2 = array();
+ preg_match('/\(\*\w*\)/', $var, $p2);
+ $p2 = $p2[0];
+
+ $p1 = substr($var, strpos($var, $p2));
+ $p2 = substr($p2, 2, strlen($p2)-3);
+ }
+ else
+ {
+ $p1 = substr($var, 0, strrpos($var, " "));
+ $p2 = substr($var, strrpos($var, " "));
+ }
+
+ if(strpos($p2, "*") !== false)
+ {
+ for($i=0; $i<substr_count($p2, "*"); $i++)
+ $p1 .= "*";
+ $p2 = str_replace("*", "", $p2);
+ }
+
+ return array(trim($p1), trim($p2));
+}
+
+function _simplify($text)
+{
+ $text = ereg_replace('\(!\( (.*)[ ]?\)\)', '!\1', $text);
+ $text = ereg_replace('\(\(([^ ])\)\)', '\1', $text);
+ return $text;
+}
+
+function clean_func($func)
+{
+ $func = str_replace(array(" ", " "), " ", $func);
+ $func = str_replace(" ", " ", $func);
+ return $func;
+}
+
+function do_see_markup($data)
+{
+ $ret = array();
+ foreach($data as $el)
+ {
+ $el = trim($el);
+
+ if(substr($el, 0, 1) != "[")
+ $ret[] = do_markup("[F[".$el."]]");
+ else
+ $ret[] = do_markup($el);
+ }
+
+ return implode(" &amp; ", $ret);
+}
+
+function do_markup($data)
+{
+ global $svn, $wiki;
+
+ $data = ereg_replace('=([^=]*)=', '<code>\1</code>', $data);
+ $data = ereg_replace('\[W\[([^#\[]*)([^\[]*)\]\]', '<a href="'.$wiki.'\1\2">\1</a>', $data);
+ $data = ereg_replace('\[S\[([^\[]*)\]\]', '<a href="'.$svn.'\1?content-type=text%2Fplain">\1</a>', $data);
+ $data = ereg_replace('\[F\[([^\[]*)\]\]', '<a href="#\1">\1</a>', $data);
+ $data = ereg_replace('\[\[([^#\[]*)([^\[]*)\]\]', '<a href="\1\2">\1</a>', $data);
+ $data = str_replace("%BR%", "<br />", $data);
+ $data = nl2br($data);
+
+ return $data;
+}
+?>
diff --git a/utils/rockbox_api/gen_html.php b/utils/rockbox_api/gen_html.php
new file mode 100755
index 0000000000..34e124f411
--- /dev/null
+++ b/utils/rockbox_api/gen_html.php
@@ -0,0 +1,110 @@
+#!/usr/bin/php
+<?
+require_once("functions.php");
+
+function get_group($text)
+{
+ return str_replace(array(" ", "/"), "_", $text);
+}
+
+$input = file_get_contents($argv[1]);
+
+$inh = parse_documentation($input);
+
+@mkdir("output");
+
+$h = fopen("output/index.html", "w");
+
+fwrite($h, '<html><head><link href="layout.css" rel="stylesheet" type="text/css" /><title>Plugin API - INDEX</title></head><body>');
+
+fwrite($h, "<h1>Plugin API reference</h1>");
+fwrite($h, "<ul>");
+
+foreach($inh as $group_name => $group)
+{
+ if(strlen($group_name) > 0)
+ {
+ fwrite($h, '<li>'.ucwords($group_name)."<ul>");
+
+ foreach($group as $el_name => $el)
+ fwrite($h, "<li><a href=\"".get_group($group_name).".html#".get_func($el_name)."\">".$el_name."</a></li>");
+
+ fwrite($h, "</ul></li>");
+ }
+}
+fwrite($h, "</ul></body></html>");
+
+fclose($h);
+
+$menu = '<ul><li><a href="index.html">INDEX</a></li><ul>';
+$_menu = array();
+foreach($inh as $group_name => $group)
+{
+ if(strlen($group_name) > 0)
+ $_menu[strtolower($group_name)] = '<li><a href="'.get_group($group_name).'.html">'.ucwords($group_name).'</a></li>';
+}
+
+ksort($_menu);
+$menu .= implode("\n", $_menu);
+$menu .= "</ul></ul>";
+
+foreach($inh as $group_name => $group)
+{
+ $h = fopen("output/".get_group($group_name).".html", "w");
+
+ fwrite($h, '<html><head><link href="layout.css" rel="stylesheet" type="text/css" /><title>Plugin API - '.ucwords($group_name).'</title></head><body>');
+ fwrite($h, '<div id="menu">'.ucwords($menu).'</div>');
+ fwrite($h, '<div id="content">');
+ fwrite($h, '<a link="top"></a>');
+
+ fwrite($h, "<h2>".ucwords($group_name)."</h2>");
+ fwrite($h, '<span class="group">');
+ foreach($group as $func_name => $func)
+ {
+ fwrite($h, '<a id="'.get_func($func_name).'"></a>');
+
+ fwrite($h, "<h3>$func_name</h3>");
+
+ if(strlen($func["description"][0]) > 0)
+ fwrite($h, do_markup($func["description"][0])."<br /><br />");
+
+ if(isset($func["param"]))
+ {
+ $params = "";
+ foreach($func["param"] as $param)
+ {
+ $param = trim($param);
+ $p1 = substr($param, 0, strpos($param, " "));
+ $p2 = substr($param, strpos($param, " "));
+ if(strlen($p1) > 0 && strlen($p2) > 0)
+ $params .= '<dt>'.$p1.'</dt><dd> '.do_markup($p2).'</dd>';
+ }
+
+ if(strlen($params) > 0)
+ {
+ fwrite($h, '<span class="extra">Parameters:</span><dl>');
+ fwrite($h, $params);
+ fwrite($h, "</dl>");
+ }
+ }
+
+ if(isset($func["return"]) && strlen($func["return"][0]) > 0)
+ fwrite($h, '<span class="extra">Returns:</span> '.do_markup($func["return"][0]).'<br /><br />');
+
+ if(isset($func["conditions"]))
+ fwrite($h, '<span class="extra">Conditions:</span> '.$func["conditions"][0].'<br /><br />');
+
+ if(isset($func["see"]))
+ fwrite($h, '<span class="see">Also see '.do_see_markup(explode(" ", trim($func["see"][0]))).'</span><br /><br />');
+
+ fwrite($h, '<a href="#top" class="top">To top</a><hr />');
+ }
+ fwrite($h, "</span>");
+
+ fwrite($h, "</div></body></html>");
+
+ fclose($h);
+}
+
+copy("layout.css", "output/layout.css");
+?> \ No newline at end of file
diff --git a/utils/rockbox_api/generate.php b/utils/rockbox_api/generate.php
new file mode 100755
index 0000000000..29dd69588a
--- /dev/null
+++ b/utils/rockbox_api/generate.php
@@ -0,0 +1,63 @@
+#!/usr/bin/php
+<?
+require_once("functions.php");
+
+echo '# Auto generated documentation by Rockbox plugin API generator v2'."\n";
+echo '# Made by Maurus Cuelenaere'."\n";
+echo <<<MOO
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# \$Id$
+#
+# Generated from $svn\x61pps/plugin.h
+#
+# Format:
+# \\group memory and strings
+# \\conditions defined(HAVE_BACKLIGHT)
+# \\param fmt
+# \\return
+# \\description
+# \\see func1 func2 [S[apps/plugin.c]]
+#
+# Markup:
+# [W[wiki url]]
+# [S[svn url]]
+# [F[function]]
+# [[url]]
+# %BR%
+# =code=
+
+MOO;
+
+foreach(get_newest() as $line)
+{
+ echo "\n".clean_func($line["func"])."\n";
+
+ if(strlen($line["group"]) > 0)
+ echo " \\group ".$line["group"]."\n";
+
+ if(strlen($line["cond"]) > 2)
+ echo " \\conditions "._simplify($line["cond"])."\n";
+
+ foreach(get_args($line["func"]) as $param)
+ {
+ if(strlen($param) > 0 && $param != "...")
+ {
+ $param = split_var($param);
+ $param = $param[1];
+ echo " \\param $param\n";
+ }
+ }
+
+ if(get_return($line["func"]) !== false)
+ echo " \\return\n";
+
+ echo " \\description\n";
+}
+
+echo "\n# END\n";
+?> \ No newline at end of file
diff --git a/utils/rockbox_api/layout.css b/utils/rockbox_api/layout.css
new file mode 100644
index 0000000000..09e7391197
--- /dev/null
+++ b/utils/rockbox_api/layout.css
@@ -0,0 +1,108 @@
+body
+{
+ font-family: Verdana;
+}
+
+li
+{
+ font-size: 10px;
+}
+
+code
+{
+ color: #00A;
+}
+
+.see, .see a
+{
+ color: #559;
+}
+
+.group
+{
+ font-size: 12px;
+}
+
+.group h3
+{
+ font-size: 14px;
+}
+
+h2
+{
+ color: #D11;
+}
+
+a
+{
+ color: blue;
+}
+
+a:hover
+{
+ color: red;
+}
+
+.top
+{
+ font-size: 10px;
+ color: green;
+}
+
+.extra
+{
+ font-weight: bold;
+ color: #992;
+}
+
+dl
+{
+ border-left: 1px solid #CCC;
+ padding-left: 10px;
+}
+
+dt, dd
+{
+ font-style: normal;
+}
+
+dd
+{
+ margin-left: 12em;
+}
+
+dt
+{
+ clear: left;
+ display: block;
+ float: left;
+ font-weight: bold;
+ width: 12em;
+}
+
+hr
+{
+ border: 1px solid #CCCCCC;
+ margin: 1em 0;
+}
+
+#content
+{
+ margin-left: 14em;
+ margin-right: 1em;
+ padding: 0;
+}
+
+#menu
+{
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ width: 14em;
+ padding: 0;
+}
+
+#menu ul
+{
+ padding-left: 1em;
+} \ No newline at end of file
diff --git a/utils/rockbox_api/update.php b/utils/rockbox_api/update.php
new file mode 100755
index 0000000000..ef4a456d12
--- /dev/null
+++ b/utils/rockbox_api/update.php
@@ -0,0 +1,119 @@
+#!/usr/bin/php
+<?
+require_once("functions.php");
+
+$input = file_get_contents($argv[1]);
+
+$input = parse_documentation($input);
+
+foreach($input as $rootname => $rootel)
+{
+ foreach($rootel as $name => $el)
+ $input[$name] = $el;
+ unset($input[$rootname]);
+}
+
+$new = get_newest();
+
+foreach($new as $name => $el)
+{
+ unset($new[$name]);
+ $name = clean_func($el["func"]);
+
+ $new[$name] = array(
+ "group" => array($el["group"]),
+ "description" => array("")
+ );
+
+ if(strlen($el["cond"]) > 2)
+ $new[$name]["conditions"][0] = $el["cond"];
+
+ $args = get_args($el["func"]);
+ if(count($args) > 0)
+ {
+ foreach($args as $n => $arg)
+ {
+ $tmp = split_var($arg);
+ $args[$n] = $tmp[1];
+ }
+ $new[$name]["param"] = $args;
+ }
+
+ if(get_return($el["func"]) !== false)
+ $new[$name]["return"][0] = "";
+}
+
+
+$merged = array_merge($new, $input);
+
+uksort($merged, "func_sort");
+
+echo '# Auto generated documentation by Rockbox plugin API generator v2'."\n";
+echo '# Made by Maurus Cuelenaere'."\n";
+echo <<<MOO
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# \$Id$
+#
+# Generated from $svn\x61pps/plugin.h
+#
+# Format:
+# \\group memory and strings
+# \\conditions defined(HAVE_BACKLIGHT)
+# \\param fmt
+# \\return
+# \\description
+# \\see func1 func2 [S[apps/plugin.c]]
+#
+# Markup:
+# [W[wiki url]]
+# [S[svn url]]
+# [F[function]]
+# [[url]]
+# %BR%
+# =code=
+
+MOO;
+
+foreach($merged as $func => $line)
+{
+ echo "\n".clean_func($func)."\n";
+
+ if(strlen($line["group"]) > 0)
+ echo " \\group ".trim($line["group"][0])."\n";
+
+ if(strlen($line["conditions"]) > 2)
+ echo " \\conditions ".trim(_simplify($line["conditions"][0]))."\n";
+
+ if(isset($line["param"]))
+ {
+ foreach($line["param"] as $param)
+ {
+ if($param != "...")
+ echo " \\param ".trim($param)."\n";
+ }
+ }
+
+ if(isset($line["return"]))
+ {
+ if(trim($line["return"]) == "")
+ echo " \\return\n";
+ else
+ echo " \\return ".trim($line["return"][0])."\n";
+ }
+
+ if(trim($line["description"]) == "")
+ echo " \\description\n";
+ else
+ echo " \\description ".trim($line["description"][0])."\n";
+
+ if(isset($line["see"]))
+ echo " \\see ".trim($line["see"][0])."\n";
+}
+
+echo "\n# END\n";
+?> \ No newline at end of file