PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/pyplusplus_dev_0.9.5/contrib/arrayinfo/createarrayinfo.py

https://github.com/gatoatigrado/pyplusplusclone
Python | 169 lines | 117 code | 18 blank | 34 comment | 17 complexity | dc728b7422c673ed71ae6021cd1e6c53 MD5 | raw file
  1. #!/usr/bin/env python
  2. ######################################################################
  3. # This tool parses header files inside a directory and stores info
  4. # about the array size of function arguments into a file for later
  5. # retrieval.
  6. #
  7. # usage: createarrayinfo.py [options] <headerpath>
  8. #
  9. # options:
  10. # -h, --help show this help message and exit
  11. # -o FILENAME, --output=FILENAME
  12. # Output file name (default: stdout)
  13. # -a ARGSTRING, --cppargs=ARGSTRING
  14. # Additional C preproceesor arguments
  15. #
  16. # Author: Matthias Baas (baas@ira.uka.de)
  17. ######################################################################
  18. import sys, os, os.path, glob, optparse
  19. from cpptokenize import *
  20. # Parser
  21. class Parser:
  22. """Parser class.
  23. This class contains the token eater method that processes the tokens
  24. generated by cpptokenize.
  25. Whenever a function signature is parsed a line is written to the output.
  26. """
  27. def __init__(self, headerpath, output=sys.stdout):
  28. """Constructor.
  29. """
  30. self.headerpath = os.path.normpath(headerpath)
  31. self.output = output
  32. # Buffer for the last NAME token (which might be a function name)
  33. self.lastname = None
  34. # The current state
  35. self.state = "Outside"
  36. self.classname = None
  37. self.funcname = None
  38. self.args = None
  39. self.arraysize = None
  40. self.no_arg = False
  41. self.firstline = None
  42. def tokeater(self, type, s, start, end, line, filename):
  43. """Token eater."""
  44. if type==WHITESPACE or type==NEWLINE:
  45. return
  46. method = getattr(self, "state%s"%self.state)
  47. method(type, s, start, end, line, filename)
  48. # The state methods. They are called by the token eater and must take
  49. # the same arguments than the token eater.
  50. def stateOutside(self, type, s, start, end, line, filename):
  51. if type==NAME and s=="class":
  52. self.state = "ClassName"
  53. if type==NAME:
  54. self.firstline = start[0]
  55. self.lastname = s
  56. elif self.lastname=="operator":
  57. self.lastname += s
  58. elif type==OPERATOR and s=="(":
  59. self.funcname = self.lastname
  60. self.args = []
  61. self.arraysize = None
  62. self.no_arg = True
  63. self.state = "Args"
  64. def stateClassName(self, type, s, start, end, line, filename):
  65. if s.upper()==s:
  66. return
  67. self.classname = s
  68. self.state = "Outside"
  69. def stateArgs(self, type, s, start, end, line, filename):
  70. if s==")":
  71. if not self.no_arg:
  72. self.args.append(self.arraysize)
  73. self.state = "End"
  74. elif s==",":
  75. self.args.append(self.arraysize)
  76. self.arraysize = None
  77. elif s=="[":
  78. self.state = "ArgsSize"
  79. self.no_arg = False
  80. def stateArgsSize(self, type, s, start, end, line, filename):
  81. if s=="]":
  82. self.state = "Args"
  83. else:
  84. self.arraysize = int(s)
  85. self.state = "Args"
  86. def stateEnd(self, type, s, start, end, line, filename):
  87. if s==";":
  88. if os.path.normpath(os.path.dirname(filename))==self.headerpath:
  89. self.onFuncComplete(self.classname, self.funcname, self.args, self.firstline, end[0], filename)
  90. self.state = "Outside"
  91. def onFuncComplete(self, classname, funcname, args, firstline, lastline, filename):
  92. """Callback that is called when one function is completely processed.
  93. """
  94. print >>self.output, "%s;%d;%d;%s;%s;%s"%(filename, firstline, lastline, classname, funcname, args)
  95. # parseHeader
  96. def parseHeader(filename, cpp="cpp", cppargs="", output=sys.stdout):
  97. """Parse a header file.
  98. filename is the header file name and cppargs is a string with
  99. additional arguments for the invocation of the preprocessor 'cpp'.
  100. output is the output stream.
  101. """
  102. # Run the file through the preprocessor...
  103. filename = os.path.abspath(filename)
  104. print >>sys.stderr, "Parsing",filename
  105. cmd = '%s %s "%s" >_tmp.h'%(cpp, cppargs, filename.replace(" ", "\\ "))
  106. print >>sys.stderr, cmd
  107. os.system(cmd)
  108. # Parse the preprocessed file...
  109. parser = Parser(os.path.dirname(filename), output)
  110. tokenize(file("_tmp.h").readline, parser.tokeater)
  111. ######################################################################
  112. # Preprocessor
  113. cpp = "cpp"
  114. # Preprocessor arguments
  115. cppargs = ""
  116. # Output stream
  117. output = sys.stdout
  118. usage = "usage: %prog [options] <headerpath>"
  119. op = optparse.OptionParser(usage)
  120. op.add_option("-o", "--output", metavar="FILENAME",
  121. help="Output file name")
  122. op.add_option("-a", "--cppargs", metavar="ARGSTRING", default="",
  123. help="Additional C preproceesor arguments")
  124. options, args = op.parse_args()
  125. if len(args)==0:
  126. op.print_help()
  127. sys.exit(1)
  128. if options.output!=None:
  129. print >>sys.stderr, "Output file: %s"%options.output
  130. output = file(options.output, "wt")
  131. headerpath = args[0]
  132. headernames = os.path.join(headerpath, "*.h")
  133. print >>sys.stderr, "Input files: %s"%headernames
  134. cppargs = options.cppargs
  135. print >>sys.stderr, "Preprocessor args: %s"%cppargs
  136. headers = glob.glob(headernames)
  137. print >>sys.stderr, "%d header files found"%len(headers)
  138. for header in headers:
  139. parseHeader(header, cpp, cppargs, output)