/tags/pyplusplus_dev_0.9.5/contrib/arrayinfo/createarrayinfo.py
Python | 169 lines | 114 code | 18 blank | 37 comment | 17 complexity | dc728b7422c673ed71ae6021cd1e6c53 MD5 | raw file
- #!/usr/bin/env python
- ######################################################################
- # This tool parses header files inside a directory and stores info
- # about the array size of function arguments into a file for later
- # retrieval.
- #
- # usage: createarrayinfo.py [options] <headerpath>
- #
- # options:
- # -h, --help show this help message and exit
- # -o FILENAME, --output=FILENAME
- # Output file name (default: stdout)
- # -a ARGSTRING, --cppargs=ARGSTRING
- # Additional C preproceesor arguments
- #
- # Author: Matthias Baas (baas@ira.uka.de)
- ######################################################################
- import sys, os, os.path, glob, optparse
- from cpptokenize import *
- # Parser
- class Parser:
- """Parser class.
- This class contains the token eater method that processes the tokens
- generated by cpptokenize.
- Whenever a function signature is parsed a line is written to the output.
- """
-
- def __init__(self, headerpath, output=sys.stdout):
- """Constructor.
- """
-
- self.headerpath = os.path.normpath(headerpath)
- self.output = output
- # Buffer for the last NAME token (which might be a function name)
- self.lastname = None
- # The current state
- self.state = "Outside"
- self.classname = None
- self.funcname = None
- self.args = None
- self.arraysize = None
- self.no_arg = False
- self.firstline = None
-
- def tokeater(self, type, s, start, end, line, filename):
- """Token eater."""
- if type==WHITESPACE or type==NEWLINE:
- return
- method = getattr(self, "state%s"%self.state)
- method(type, s, start, end, line, filename)
- # The state methods. They are called by the token eater and must take
- # the same arguments than the token eater.
- def stateOutside(self, type, s, start, end, line, filename):
- if type==NAME and s=="class":
- self.state = "ClassName"
- if type==NAME:
- self.firstline = start[0]
- self.lastname = s
- elif self.lastname=="operator":
- self.lastname += s
- elif type==OPERATOR and s=="(":
- self.funcname = self.lastname
- self.args = []
- self.arraysize = None
- self.no_arg = True
- self.state = "Args"
- def stateClassName(self, type, s, start, end, line, filename):
- if s.upper()==s:
- return
- self.classname = s
- self.state = "Outside"
- def stateArgs(self, type, s, start, end, line, filename):
- if s==")":
- if not self.no_arg:
- self.args.append(self.arraysize)
- self.state = "End"
- elif s==",":
- self.args.append(self.arraysize)
- self.arraysize = None
- elif s=="[":
- self.state = "ArgsSize"
- self.no_arg = False
- def stateArgsSize(self, type, s, start, end, line, filename):
- if s=="]":
- self.state = "Args"
- else:
- self.arraysize = int(s)
- self.state = "Args"
- def stateEnd(self, type, s, start, end, line, filename):
- if s==";":
- if os.path.normpath(os.path.dirname(filename))==self.headerpath:
- self.onFuncComplete(self.classname, self.funcname, self.args, self.firstline, end[0], filename)
- self.state = "Outside"
-
- def onFuncComplete(self, classname, funcname, args, firstline, lastline, filename):
- """Callback that is called when one function is completely processed.
- """
- print >>self.output, "%s;%d;%d;%s;%s;%s"%(filename, firstline, lastline, classname, funcname, args)
- # parseHeader
- def parseHeader(filename, cpp="cpp", cppargs="", output=sys.stdout):
- """Parse a header file.
- filename is the header file name and cppargs is a string with
- additional arguments for the invocation of the preprocessor 'cpp'.
- output is the output stream.
- """
- # Run the file through the preprocessor...
- filename = os.path.abspath(filename)
- print >>sys.stderr, "Parsing",filename
- cmd = '%s %s "%s" >_tmp.h'%(cpp, cppargs, filename.replace(" ", "\\ "))
- print >>sys.stderr, cmd
- os.system(cmd)
- # Parse the preprocessed file...
- parser = Parser(os.path.dirname(filename), output)
- tokenize(file("_tmp.h").readline, parser.tokeater)
- ######################################################################
- # Preprocessor
- cpp = "cpp"
- # Preprocessor arguments
- cppargs = ""
- # Output stream
- output = sys.stdout
- usage = "usage: %prog [options] <headerpath>"
- op = optparse.OptionParser(usage)
- op.add_option("-o", "--output", metavar="FILENAME",
- help="Output file name")
- op.add_option("-a", "--cppargs", metavar="ARGSTRING", default="",
- help="Additional C preproceesor arguments")
- options, args = op.parse_args()
- if len(args)==0:
- op.print_help()
- sys.exit(1)
- if options.output!=None:
- print >>sys.stderr, "Output file: %s"%options.output
- output = file(options.output, "wt")
- headerpath = args[0]
- headernames = os.path.join(headerpath, "*.h")
- print >>sys.stderr, "Input files: %s"%headernames
- cppargs = options.cppargs
- print >>sys.stderr, "Preprocessor args: %s"%cppargs
- headers = glob.glob(headernames)
- print >>sys.stderr, "%d header files found"%len(headers)
- for header in headers:
- parseHeader(header, cpp, cppargs, output)