diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-10-06 22:19:54 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-10-06 22:19:54 +0000 |
commit | 20fb47ec778abe215ca69692434ff753596319e6 (patch) | |
tree | 69665298c0f58c07a1aa9677d33ad395ad9ccd13 /utils/rockbox_api | |
parent | 34148b9a2173b0bd80b4acd18d23216ae54cb865 (diff) | |
download | rockbox-20fb47ec778abe215ca69692434ff753596319e6.tar.gz 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/rockbox_api')
-rw-r--r-- | utils/rockbox_api/README | 29 | ||||
-rwxr-xr-x | utils/rockbox_api/functions.php | 337 | ||||
-rwxr-xr-x | utils/rockbox_api/gen_html.php | 110 | ||||
-rwxr-xr-x | utils/rockbox_api/generate.php | 63 | ||||
-rw-r--r-- | utils/rockbox_api/layout.css | 108 | ||||
-rwxr-xr-x | utils/rockbox_api/update.php | 119 |
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(" & ", $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 |