From: Aldrin Martoq <amartoq@dcc.uchile.cl>
To: alsa-devel <alsa-devel@alsa-project.org>
Subject: [PATCH] 1/2 alsa-python: API coverage documentation tool
Date: Fri, 07 Mar 2008 22:47:25 -0300 [thread overview]
Message-ID: <1204940845.6474.14.camel@localhost> (raw)
[-- Attachment #1: Type: text/plain, Size: 3447 bytes --]
HG Log:
-------
Added python tool of alsa-lib C API coverage for alsa-python binding.
Description:
------------
The following patch is a python tool that shows how much of the
asoundlib API is being covered by the alsa-python binding. It works by
parsing the C source code and comparing with the official Doxygen
documentation from alsa website.
It will help the following users:
- alsa-python developers: know how is mapped the original C API, so
which python function/variable may be used.
- python binding developers: know how much of the C API is covered. It
could help for mistakes (free() instead of using
snd_ctl_card_info_free), know what is missing, and statistic interest ;)
Sample output:
--------------
Functions
---------
1 const char* snd_asoundlib_version ( void )
Returns the ALSA sound library version in ASCII format.
=> Used in : alsacard.c: asoundlib_version
Defines
-------
N/A #define SND_CONTROL_DLSYM_VERSION _dlsym_control_001
dlsym version for interface entry callback
**** NOT AVAILABLE/USED SND_CONTROL_DLSYM_VERSION ****
2 #define SND_CTL_ASYNC
Async notification (flag for open mode)
=> As constant: alsacontrol.c: open_mode["ASYNC"]
=> As constant: alsahcontrol.c: open_mode["ASYNC"]
1 #define snd_ctl_card_info_alloca ( ptr )
allocate an invalid snd_ctl_card_info_t using standard alloca
=> Used in : alsacontrol.c: pyalsacontrol_cardinfo
Stats:
------
After every section, the program shows some stats about usage. This is
the current usage of each doxygen module:
Global defines and functions
16 missing ( 94%) 0 excluded ( 0%) of 17 total ( 6% covered).
Error handling
9 missing ( 90%) 0 excluded ( 0%) of 10 total ( 10% covered).
Control Interface
137 missing ( 53%) 0 excluded ( 0%) of 257 total ( 47% covered).
High level Control Interface
21 missing ( 46%) 0 excluded ( 0%) of 46 total ( 54% covered).
Setup Control Interface
4 missing (100%) 0 excluded ( 0%) of 4 total ( 0% covered).
MIDI Sequencer
25 missing ( 61%) 7 excluded ( 17%) of 41 total ( 39% covered).
Sequencer Client Interface
15 missing ( 35%) 14 excluded ( 33%) of 43 total ( 65% covered).
Sequencer Port Interface
48 missing ( 74%) 6 excluded ( 9%) of 65 total ( 26% covered).
Sequencer Port Subscription
3 missing ( 7%) 15 excluded ( 33%) of 46 total ( 93% covered).
Sequencer Queue Interface
58 missing ( 84%) 0 excluded ( 0%) of 69 total ( 16% covered).
Sequencer Event API
42 missing ( 93%) 0 excluded ( 0%) of 45 total ( 7% covered).
Sequencer Miscellaneous
0 missing ( N/A) 0 excluded ( N/A) of 0 total ( N/A covered).
Sequencer Event Type Checks
7 missing ( 23%) 0 excluded ( 0%) of 30 total ( 77% covered).
Sequencer Event Definitions
35 missing ( 40%) 0 excluded ( 0%) of 87 total ( 60% covered).
Sequencer Middle Level Interfa
38 missing ( 78%) 0 excluded ( 0%) of 49 total ( 22% covered).
Sequencer event <-> MIDI byte
11 missing (100%) 0 excluded ( 0%) of 11 total ( 0% covered).
Mixer Interface
44 missing ( 75%) 0 excluded ( 0%) of 59 total ( 25% covered).
Simple Mixer Interface
14 missing ( 18%) 0 excluded ( 0%) of 78 total ( 82% covered).
Cheers!
--
Aldrin Martoq <amartoq@dcc.uchile.cl>
[-- Attachment #2: doc-alsa-python-coverage --]
[-- Type: text/x-patch, Size: 25733 bytes --]
diff --git a/doc/.hgignore b/doc/.hgignore
new file mode 100644
--- /dev/null
+++ b/doc/.hgignore
@@ -0,0 +1,3 @@
+syntax: glob
+
+cache/*
diff --git a/doc/APICoverage.py b/doc/APICoverage.py
new file mode 100644
--- /dev/null
+++ b/doc/APICoverage.py
@@ -0,0 +1,385 @@
+#! /usr/bin/python
+
+# APICoverage.py -- helper for API coverage tools
+# Copyright(C) 2008 by Aldrin Martoq <amartoq@dcc.uchile.cl>
+# Licensed under GPL v2 (see below).
+#
+# Description:
+# This file provides the base for creating an API coverage tool. It may
+# be used in other projects, for an example see the coverage.py tool.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+import os, pickle, urllib, sys
+from pyparsing import *
+from htmlentitydefs import entitydefs
+from htmllib import HTMLParser
+from formatter import AbstractFormatter, DumbWriter
+
+# cache dir (preparsed source and HTML asoundlib API)
+cache = 'cache'
+# directory of source code
+source_dir = '.'
+# base url
+api_url = ''
+# summary (section) counter
+summary_total = summary_miss = summary_exc = 0
+# subsection (defines, typedefs, etc) counter
+count_total = count_miss = count_exc = 0
+
+if not os.path.exists(cache):
+ print "Creating cache dir: %s" % cache
+ os.makedirs(cache)
+
+def read_source(name):
+ """ Reads the specified source file """
+ filename = os.path.join(source_dir, name)
+ return (name, "".join(open(filename).readlines()), filename)
+
+def list_to_str(alist):
+ tmp = []
+ for i in alist:
+ if type(i) is ParseResults:
+ tmp.append(list_to_str(i))
+ else:
+ tmp.append(str(i))
+ return tmp
+
+
+def get_cached_parse(index_parser_list, name):
+ """
+ Generate the scan lists from the parsers, store it in a file in the
+ cachedir and return it; if the file already exists it just return it
+ without processing.
+ """
+ name = os.path.join(cache, name)
+
+ if os.path.exists(name):
+ modified = False
+ for source, parser in index_parser_list:
+ if os.stat(source[2]).st_mtime > os.stat(name).st_mtime:
+ modified = True
+ if not modified:
+ return pickle.load(open(name))
+
+ print "generating cache, file: %s" % name,
+ dict = {}
+ for source, parser in index_parser_list:
+ print source[0],
+ sys.stdout.flush()
+ list = []
+ for tokenlist, start, end in parser.scanString(source[1]):
+ tlist = list_to_str(tokenlist)
+ list.append((tlist, int(start), int(end)))
+ dict[source[0]] = list
+ pickle.dump(dict, open(name, "wb"))
+ print
+ return dict
+
+# API html parsing/caching
+
+def get_cached_api(url, name):
+ """
+ Download the HTML API from the specified url and stores it in a
+ file in the cachedir; if the file already exists it just returns it
+ contents.
+ """
+ name = os.path.join(cache, name)
+ if os.path.exists(name):
+ data = "".join(open(name).readlines())
+ else:
+ print "downloading %s" % url
+ data = urllib.urlopen(url).read()
+ open(name, "w").write(data)
+ return data
+
+
+
+class AsoundlibAPIHTMLParser(HTMLParser):
+ """
+ Customized HTMLParser, it adds some markers for easy parsing the
+ HTML asoundlib API from the alsa website.
+ """
+
+ HTMLParser.entitydefs['nbsp'] = ' '
+
+ def __init__(self, name, data):
+ f = AbstractFormatter(DumbWriter(open(name, 'w'), 100))
+ HTMLParser.__init__(self, f)
+ self.feed(data)
+ self.close()
+
+ def start_h1(self, attrs):
+ HTMLParser.start_h1(self, attrs)
+ self.handle_data("--- titlestart")
+ self.do_br(None)
+
+ def start_table(self, attrs):
+ if len(attrs) == 1 and attrs[0] == ("class", "memname"):
+ self.handle_data("--- itemstart")
+ self.do_br(None)
+
+ def start_tr(self, attrs):
+ self.do_br(None)
+
+ def anchor_end(self):
+ pass
+
+def parse_asoundlib_api(lines):
+ """
+ Parses an html file (given as a set of lines including '\n').
+ Returns a list of: title, defines, typedefs, enums, functions.
+ """
+ state = 0
+ defines = []
+ typedefs = []
+ enums = []
+ functions = []
+ current = None
+ title = None
+ name = ""
+ comment = ""
+ enumsublist = []
+ for line in lines:
+ line = line[:-1]
+ if False:
+ if id(current) == id(defines):
+ print "defines ",
+ elif id(current) == id(typedefs):
+ print "typedefs ",
+ elif id(current) == id(enums):
+ print "enums ",
+ elif id(current) == id(functions):
+ print "functions ",
+ else:
+ print " ",
+ print "%s %d %s" % (id(current), state, line)
+
+ if line.startswith('Define Documentation'):
+ current = defines
+ state = 0
+ elif line.startswith('Typedef Documentation'):
+ current = typedefs
+ state = 0
+ elif line.startswith('Enumeration Type Documentation'):
+ current = enums
+ state = 0
+ elif line.startswith('Function Documentation'):
+ current = functions
+ state = 0
+ elif line.startswith('--- itemstart'):
+ state = 1
+ elif line.startswith('--- titlestart'):
+ state = 5
+ elif state == 5:
+ title = line
+ state = 0
+ elif current == None:
+ continue
+ elif state == 1:
+ if line == "":
+ state = 2
+ else:
+ name += line
+ elif state == 2:
+ if id(current) == id(enums):
+ state = 3
+ else:
+ comment = line
+ current.append((name, comment))
+ name = ""
+ comment = ""
+ state = 0
+ elif state == 3 and line.startswith('Enumerator:'):
+ state = 4
+ enumsublist = []
+ elif state == 4:
+ if line == "":
+ current.append((name, comment, enumsublist))
+ name = ""
+ comment = ""
+ state = 0
+ else:
+ enum, subcomment = line.split(' ', 1)
+ enumsublist.append((enum, subcomment))
+
+ return (title, defines, typedefs, enums, functions)
+
+
+def print_name(d0, d1, name, look_constant, look_usage, exclude_list):
+ """
+ Prints a defined entry (typedef, function, etc) and its usage to stdout.
+ It also updates counters ({summary,count}_{total,miss,exc}).
+
+ Parameters:
+ d0 -- entry prototype
+ d1 -- entry documentation (one liner)
+ name -- entry name (define, function name, etc)
+ look_constant -- lookup name for constant (a defined python function)
+ look_usage -- lookup name for usage (a defined python function)
+ """
+ global summary_total, summary_miss, summary_exc
+ global count_total, count_miss, count_exc
+ summary_total += 1
+ count_total += 1
+ lc = look_constant(name)
+ uc = look_usage(name)
+ usecount = len(lc) + len(uc)
+ exccount = 0
+ for token, comment in exclude_list:
+ if token == name:
+ exccount += 1
+ if usecount == 0:
+ if exccount > 0:
+ used = "EXC"
+ summary_exc += 1
+ count_exc += 1
+ else:
+ used = "N/A"
+ summary_miss += 1
+ count_miss += 1
+ else:
+ used = "%s" % usecount
+
+ print "%-4s%s" % (used, d0)
+ print "%8s%s" % ("", d1)
+
+ if usecount > 0:
+ excstr = "Comment"
+ else:
+ excstr = "Excluded"
+ for token, comment in exclude_list:
+ if token == name:
+ print "%10s==> %11s: %s" % ("", excstr, comment)
+ for s in lc:
+ print "%10s=> As constant: %s" % ("", s)
+ for s in uc:
+ print "%10s=> Used in : %s" % ("", s)
+ if used == "N/A":
+ print " "*10 + "**** NOT AVAILABLE/USED %s ****" % name
+
+
+def _print_stat(title, section, missing, excluded, total):
+ if total == 0:
+ fmissing = "N/A"
+ fexcluded = "N/A"
+ fcovered = "N/A"
+ else:
+ fmissing = (100*(float(missing)/float(total)))
+ fexcluded = (100*(float(excluded)/float(total)))
+ fcovered = 100 - fmissing
+ fmissing = "%3.0f%%" % fmissing
+ fexcluded = "%3.0f%%" % fexcluded
+ fcovered = "%3.0f%%" % fcovered
+ print "STAT %-30.30s %-12.12s: " % (title, section) + \
+ "%3d missing (%4s) %3d excluded (%4s) of %3d total (%4s covered)." % \
+ (missing, fmissing, excluded, fexcluded, total, fcovered)
+
+
+def print_stat(title, section):
+ """
+ Print STATS line for the given title and section. It will
+ reset the section counters (count_{total,miss}).
+ """
+ global count_total, count_miss, count_exc
+ _print_stat(title, section, count_miss, count_exc, count_total)
+ count_total = count_miss = count_exc = 0
+
+def print_summary_stat(title):
+ """
+ Print STATS line for the last given title and section. It will
+ reset the title summary counters (summary_{total,miss}).
+ """
+ global summary_total, summary_miss, summary_exc
+ _print_stat(title, "SUMMARY", summary_miss, summary_exc, summary_total)
+ summary_total = summary_miss = summary_exc = 0
+
+
+def parse_excludes(excludes):
+ list = []
+ for line in excludes.splitlines():
+ s = line.split(' ', 1)
+ if len(s) > 1:
+ token = s[0]
+ comment = s[1]
+ list.append((token, comment))
+ return list
+
+
+
+def print_api_coverage(urls, look_constant, look_usage, excludes):
+
+ el = parse_excludes(excludes)
+
+ for url in urls:
+ data = get_cached_api(api_url + url, url)
+ tmp = os.path.join(cache, 'tmp')
+ AsoundlibAPIHTMLParser(tmp, data)
+ (title, defines, typedefs, enums, functions) = \
+ parse_asoundlib_api(open(tmp).readlines())
+ print title
+ print "="*len(title)
+ print "\n"*2
+ #print "%s\n%s\n%s\n%s\n%s\n\n" % \
+ # (title, defines, typedefs, enums, functions)
+ summary_total = 0
+ summary_miss = 0
+ if len(defines) > 0:
+ print "Defines"
+ print "-------"
+ for d in defines:
+ name = d[0].split(' ')[1]
+ print_name(d[0], d[1], name, look_constant, look_usage, el)
+ print_stat(title, "Defines")
+ print "\n"*2
+ if len(typedefs) > 0:
+ print "Typedefs"
+ print "--------"
+ for d in typedefs:
+ names = d[0].split(' ')
+ name = names[-1]
+ if ')' in name:
+ names = d[0].split('(')
+ name = names[-2].split()[-1]
+ print_name(d[0], d[1], name, look_constant, look_usage, el)
+ print_stat(title, "Typedefs")
+ print "\n"*2
+ if len(enums) > 0:
+ print "Enumerations"
+ print "------------"
+ for e in enums:
+ print "%s" % e[0]
+ for d in e[2]:
+ name = d[0]
+ print_name(d[0], d[1], name, look_constant, look_usage, el)
+ print_stat(title, "Enumerations")
+ print "\n"*2
+ if len(functions) > 0:
+ print "Functions"
+ print "---------"
+ for d in functions:
+ name = None
+ for n in d[0].split(' '):
+ if n.startswith('snd_'):
+ name = n
+ elif n.startswith('('):
+ break
+ if name != None:
+ print_name(d[0], d[1], name, look_constant, look_usage, el)
+ print_stat(title, "Functions")
+ print "\n"*2
+ print_summary_stat(title)
+ print "\n"*4
+
diff --git a/doc/alsa-python-coverage.py b/doc/alsa-python-coverage.py
new file mode 100755
--- /dev/null
+++ b/doc/alsa-python-coverage.py
@@ -0,0 +1,364 @@
+#! /usr/bin/python
+
+# coverage.py -- python coverage of asoundlib API
+# Copyright(C) 2008 by Aldrin Martoq <amartoq@dcc.uchile.cl>
+# Licensed under GPL v2 (see below).
+#
+# Description:
+# This tool aims to help in completing the python binding of the asoundlib
+# API. Actually, it's being coded for the current pyalsa, but it can be
+# easily modified to support other styles of codes (mainly by changing the
+# pyparsing objects used to scan the source code).
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+from APICoverage import *
+import APICoverage
+from pprint import pprint
+import time
+
+__author__ = "Aldrin Martoq <amartoq@dcc.uchile.cl>"
+__version__ = "1.0"
+__license__ = "GNU General Public License version 2"
+__copyright__ = "Copyright(C) 2008 by Aldrin Martoq <amartoq@dcc.uchile.cl>"
+
+
+# setup and do the work
+APICoverage.source_dir = '../pyalsa'
+APICoverage.api_url = 'http://www.alsa-project.org/alsa-doc/alsa-lib/'
+
+time_start = time.time()
+
+# common C parser
+ident = Word(alphas + "_", alphanums + "_")
+type_and_var = \
+ Optional(oneOf("const unsigned struct")) \
+ + ident + Optional(Word("*")) + ident
+args = OneOrMore(type_and_var) + ZeroOrMore("," + type_and_var)
+function_declaration = type_and_var + "(" + Group(args) + ")"
+function_define = \
+ "#define" + ident \
+ + "(" + OneOrMore(ident) + ZeroOrMore("," + ident) + Optional("...") + ")"
+function_define_block = \
+ "#define" + ident + "{"
+# + Group(("(" + args + Optional("...") + ")") | "{")
+
+# common asoundlib parser
+snd_ = Regex("snd_[\w_]+")
+SND_ = Regex("SND_[\w_]+")
+
+# pyalsa/alsaseq.c parser
+alsaseq_SEQ = Regex("SEQ_[\w_]+")
+alsaseq_Constant = \
+ "TCONSTADD(module," + alsaseq_SEQ + "," + quotedString + "," + alsaseq_SEQ
+alsaseq_typedef = \
+ Literal("typedef") \
+ + "struct" \
+ + "{" \
+ + "PyObject_HEAD" \
+ + Optional(";") \
+ + OneOrMore((type_and_var + ";") | cppStyleComment) \
+ + "}" \
+ + ident.setName("struct_name")
+alsaseq_function = \
+ "static" \
+ + function_declaration.setName("static_function")
+alsaseq_index = function_define | function_define_block \
+ | alsaseq_typedef | alsaseq_function
+
+# pyalsa/{alsacard, alsacontrol, alsahcontrol, alsamixer}.c parser
+addspace = Regex("add_space[0-9]")
+addspace_def = \
+ Suppress(addspace + "(") \
+ + quotedString + Suppress(",") + ident + Suppress(");")
+alsaall_Constant = \
+ Suppress(Literal("#define") \
+ + addspace \
+ + "(pname, name) { \\" \
+ + "o = PyInt_FromLong(") \
+ + SND_ \
+ + Suppress("##name); \\") \
+ + Suppress("PyDict_SetItemString(d1, pname, o); \\") \
+ + Suppress("Py_DECREF(o); }") \
+ + OneOrMore(Group(addspace_def)) \
+ + Suppress("PyDict_SetItemString(d,") \
+ + quotedString
+
+
+
+alsaall_typedef = \
+ Literal("struct") \
+ + "{" \
+ + "PyObject_HEAD" \
+ + Optional(";") \
+ + OneOrMore((type_and_var + ";") | cppStyleComment) \
+ + "}"
+alsaall_function = \
+ "static" \
+ + function_declaration.setName("static_function")
+alsaall_index = function_define | alsaall_typedef | alsaall_function
+
+# read all files
+pyalsaseq = read_source('alsaseq.c')
+pyalsacard = read_source('alsacard.c')
+pyalsacontrol = read_source('alsacontrol.c')
+pyalsahcontrol = read_source('alsahcontrol.c')
+pyalsamixer = read_source('alsamixer.c')
+
+# parse all files with parser
+index = get_cached_parse([
+ (pyalsaseq, alsaseq_index),
+ (pyalsacard, alsaall_index),
+ (pyalsacontrol, alsaall_index),
+ (pyalsahcontrol, alsaall_index),
+ (pyalsamixer, alsaall_index)
+ ], "index")
+index_snd_ = get_cached_parse([
+ (pyalsaseq, snd_),
+ (pyalsacard, snd_),
+ (pyalsacontrol, snd_),
+ (pyalsahcontrol, snd_),
+ (pyalsamixer, snd_)
+ ], "index_snd_")
+index_SND_ = get_cached_parse([
+ (pyalsaseq, SND_),
+ (pyalsacard, SND_),
+ (pyalsacontrol, SND_),
+ (pyalsahcontrol, SND_),
+ (pyalsamixer, SND_)
+ ], "index_SND_")
+index_Constant_alsaseq = get_cached_parse([
+ (pyalsaseq, alsaseq_Constant)
+ ], "index_Constant_alsaseq")
+index_Constant_alsaall = get_cached_parse([
+ (pyalsacard, alsaall_Constant),
+ (pyalsacontrol, alsaall_Constant),
+ (pyalsahcontrol, alsaall_Constant),
+ (pyalsamixer, alsaall_Constant)
+ ], "index_Constant_alsaall")
+
+# urls of doxygen documentation
+urls = [
+ # globals
+ "group___global.html",
+ # error handling
+ "group___error.html",
+ # control
+ "group___control.html",
+ "group___h_control.html",
+ "group___s_control.html",
+ # sequencer
+ "group___sequencer.html",
+ "group___seq_client.html",
+ "group___seq_port.html",
+ "group___seq_subscribe.html",
+ "group___seq_queue.html",
+ "group___seq_event.html",
+ "group___seq_misc.html",
+ "group___seq_ev_type.html",
+ "group___seq_events.html",
+ "group___seq_middle.html",
+ "group___m_i_d_i___event.html",
+ # mixer
+ "group___mixer.html",
+ "group___simple_mixer.html"
+ ]
+
+def look_constant(name):
+ """
+ Look name for constant declarations.
+
+ Returns:
+ a list of strings with the file and python constant.
+ """
+ nlist = []
+ for file in index_Constant_alsaseq:
+ for lc in index_Constant_alsaseq[file]:
+ tokens, start, end = lc
+ rs = "SND_" + tokens[5]
+ if rs == name:
+ nlist.append("%14s: %s" % (file, tokens[5]))
+ nlist.append("%14s: %s[%s]" %
+ (file, tokens[1].lower(), tokens[3]))
+ for file in index_Constant_alsaall:
+ for lc in index_Constant_alsaall[file]:
+ tokens, start, end = lc
+ prefix = tokens[0]
+ dictname = tokens[-1].split('"')[1]
+ for i in range(1, len(tokens)-1):
+ rs = prefix + tokens[i][1]
+ if rs == name:
+ nlist.append("%14s: %s[%s]" %
+ (file, dictname, tokens[i][0]))
+
+ return nlist
+
+def look_usage(name):
+ """
+ Look name for usage (appareance) in C functions, structs, etc.
+
+ Returns:
+ a list of strings with the file and matched function/struct/define.
+ """
+ name = name.strip()
+ dict = {}
+ for file in index_snd_:
+ list = []
+ for lu in index_snd_[file]:
+ tokens, start, end = lu
+ rs = tokens[0]
+ if rs == name:
+ list.append(start)
+ dict[file] = list
+ for file in index_SND_:
+ list = []
+ for lu in index_SND_[file]:
+ tokens, start, end = lu
+ rs = tokens[0]
+ if rs == name:
+ list.append(start)
+ if dict.has_key(file):
+ dict[file].extend(list)
+ else:
+ dict[file] = list
+
+ nlist = []
+ for file in dict:
+ for lstart in dict[file]:
+ if not index.has_key(file):
+ continue
+ found = None
+ previous = None
+ for call in index[file]:
+ tokens, start, end = call
+ if start > lstart:
+ found = previous
+ break
+ previous = tokens[2]
+ if tokens[0] == 'typedef':
+ previous = tokens[-1]
+ elif tokens[0] == '#define':
+ previous = tokens[1]
+ elif previous == '*':
+ previous = tokens[3]
+ #print "%8s: %5d - %20s %s" % (file, start, name, previous)
+ if found != None:
+ nlist.append("%14s: %s" % (file, found))
+ #print "FOUND: %8s: %5d %s" % (file, lstart, found)
+ return nlist
+
+
+# Following string contains excluded/commented API tokens, one per line.
+# Format is:
+# token comment
+comments = """
+SND_SEQ_DLSYM_VERSION I think there is no real use in pyalsa
+
+snd_seq_open_lconf need a snd_config port for implementing it
+snd_seq_poll_descriptors_revents no real use in pyalsa
+snd_seq_system_info_copy no real use in pyalsa
+snd_seq_system_info_free no real use in pyalsa
+snd_seq_system_info_malloc snd_seq_system_info_alloca used instead
+snd_seq_system_info_sizeof currently not used
+
+snd_seq_client_info_copy no real use in pyalsa
+snd_seq_client_info_free no real use in pyalsa
+snd_seq_client_info_malloc snd_seq_client_info_alloca used instead
+snd_seq_client_pool_copy no real use in pyalsa
+snd_seq_client_pool_free no real use in pyalsa
+snd_seq_client_pool_get_client snd_seq_client_id used instead
+snd_seq_client_pool_malloc no real use in pyalsa
+snd_seq_client_pool_set_input_pool snd_seq_set_client_pool_input used instead
+snd_seq_client_pool_set_output_pool snd_seq_set_client_pool_output used instead
+snd_seq_client_pool_set_output_room snd_seq_set_client_pool_output_room used instead
+snd_seq_client_pool_sizeof currently not used
+snd_seq_set_client_pool snd_seq_set_client_pool_* used instead
+snd_seq_client_info_set_name snd_seq_set_client_name used instead
+snd_seq_client_info_sizeof currently not used
+
+snd_seq_get_port_info snd_seq_get_any_port_info used instead
+snd_seq_port_info_copy no real use in pyalsa
+snd_seq_port_info_free no real use in pyalsa
+snd_seq_port_info_malloc snd_seq_port_info_alloca used instead
+snd_seq_port_info_set_addr snd_seq_port_info_set_client, snd_seq_port_info_set_port used instead
+snd_seq_port_info_sizeof currently not used
+
+snd_seq_port_subscribe_copy no real use in pyalsa
+snd_seq_port_subscribe_free no real use in pyalsa
+snd_seq_port_subscribe_malloc snd_seq_port_subscribe_alloca used instead
+snd_seq_port_subscribe_sizeof currently not used
+snd_seq_query_subscribe_copy no real use in pyalsa
+snd_seq_query_subscribe_free no real use in pyalsa
+snd_seq_query_subscribe_get_client snd_seq_query_subscribe_get_addr used instead
+snd_seq_query_subscribe_get_index currently not used
+#snd_seq_query_subscribe_get_num_subs
+snd_seq_query_subscribe_get_port snd_seq_query_subscribe_get_addr used instead
+snd_seq_query_subscribe_get_root currently not used
+snd_seq_query_subscribe_get_type currently not used
+snd_seq_query_subscribe_malloc no real use in pyalsa
+snd_seq_query_subscribe_set_client snd_seq_query_subscribe_set_index used instead
+snd_seq_query_subscribe_set_port snd_seq_query_subscribe_set_index used instead
+snd_seq_query_subscribe_sizeof currently not used
+"""
+
+
+print """
+*******************************
+PYALSA/ASOUNDLIB COVERAGE/USAGE
+*******************************
+
+
+Notes:
+* For re-generating this file, you need inet access (for downloading the
+ doxygen HTML from www.alsa-project.org site).
+* Some cached information about parsing is in the 'cache' directory:
+ * If you change a source file, the program will regenerate the cache.
+ * HTML API from www.alsa-project.org is never refreshed, remove manually.
+* Doxygen Modules are underlined by ======= .
+* Doxygen Sections are Underlined by ------- . The parsed sections are:
+ * CPP #defines
+ * Type definitions
+ * Enumerations
+ * Functions
+* The first line of each item is the "C Prototype". First 3 columns are:
+ * Number of times found in checked code
+ * N/A if the item is not being used/was not found
+ * EXC if the item is excluded (will not be used/implemented)
+* The next line is the one-liner documentation.
+* Following lines are usage/definition until next item.
+* There are lines that summaries the coverage, they start with '^STAT'.
+
+
+
+"""
+
+
+print_api_coverage(urls, look_constant, look_usage, comments)
+
+# print end line
+time_end = time.time()
+time_diff = time_end - time_start
+
+print """%s
+Generated for ALSA project by alsa-python-coverage.py %s
+%s UTC (%s@%s %3.3f seconds).
+""" % ("-"*72,
+ __version__,
+ time.asctime(time.gmtime(time_start)),
+ os.getlogin(),
+ os.uname()[1],
+ time_diff
+ )
+print
[-- Attachment #3: Type: text/plain, Size: 160 bytes --]
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
next reply other threads:[~2008-03-08 1:47 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-03-08 1:47 Aldrin Martoq [this message]
2008-03-18 17:16 ` [PATCH] 1/2 alsa-python: API coverage documentation tool Takashi Iwai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1204940845.6474.14.camel@localhost \
--to=amartoq@dcc.uchile.cl \
--cc=alsa-devel@alsa-project.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.