jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
3.0KB

  1. #! /usr/bin/env python
  2. # encoding: utf-8
  3. # DC 2008
  4. # Thomas Nagy 2010 (ita)
  5. import re
  6. from waflib import Utils, Task, TaskGen, Logs
  7. from waflib.TaskGen import feature, before_method, after_method, extension
  8. from waflib.Configure import conf
  9. INC_REGEX = """(?:^|['">]\s*;)\s*(?:|#\s*)INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])"""
  10. USE_REGEX = """(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)"""
  11. MOD_REGEX = """(?:^|;)\s*MODULE(?!\s*PROCEDURE)(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)"""
  12. re_inc = re.compile(INC_REGEX, re.I)
  13. re_use = re.compile(USE_REGEX, re.I)
  14. re_mod = re.compile(MOD_REGEX, re.I)
  15. class fortran_parser(object):
  16. """
  17. This parser will return:
  18. * the nodes corresponding to the module names that will be produced
  19. * the nodes corresponding to the include files used
  20. * the module names used by the fortran file
  21. """
  22. def __init__(self, incpaths):
  23. self.seen = []
  24. """Files already parsed"""
  25. self.nodes = []
  26. """List of :py:class:`waflib.Node.Node` representing the dependencies to return"""
  27. self.names = []
  28. """List of module names to return"""
  29. self.incpaths = incpaths
  30. """List of :py:class:`waflib.Node.Node` representing the include paths"""
  31. def find_deps(self, node):
  32. """
  33. Parse a fortran file to read the dependencies used and provided
  34. :param node: fortran file to read
  35. :type node: :py:class:`waflib.Node.Node`
  36. :return: lists representing the includes, the modules used, and the modules created by a fortran file
  37. :rtype: tuple of list of strings
  38. """
  39. txt = node.read()
  40. incs = []
  41. uses = []
  42. mods = []
  43. for line in txt.splitlines():
  44. # line by line regexp search? optimize?
  45. m = re_inc.search(line)
  46. if m:
  47. incs.append(m.group(1))
  48. m = re_use.search(line)
  49. if m:
  50. uses.append(m.group(1))
  51. m = re_mod.search(line)
  52. if m:
  53. mods.append(m.group(1))
  54. return (incs, uses, mods)
  55. def start(self, node):
  56. """
  57. Start the parsing. Use the stack self.waiting to hold the nodes to iterate on
  58. :param node: fortran file
  59. :type node: :py:class:`waflib.Node.Node`
  60. """
  61. self.waiting = [node]
  62. while self.waiting:
  63. nd = self.waiting.pop(0)
  64. self.iter(nd)
  65. def iter(self, node):
  66. """
  67. Process a single file in the search for dependencies, extract the files used
  68. the modules used, and the modules provided.
  69. """
  70. path = node.abspath()
  71. incs, uses, mods = self.find_deps(node)
  72. for x in incs:
  73. if x in self.seen:
  74. continue
  75. self.seen.append(x)
  76. self.tryfind_header(x)
  77. for x in uses:
  78. name = "USE@%s" % x
  79. if not name in self.names:
  80. self.names.append(name)
  81. for x in mods:
  82. name = "MOD@%s" % x
  83. if not name in self.names:
  84. self.names.append(name)
  85. def tryfind_header(self, filename):
  86. """
  87. Try to find an include and add it the nodes to process
  88. :param filename: file name
  89. :type filename: string
  90. """
  91. found = None
  92. for n in self.incpaths:
  93. found = n.find_resource(filename)
  94. if found:
  95. self.nodes.append(found)
  96. self.waiting.append(found)
  97. break
  98. if not found:
  99. if not filename in self.names:
  100. self.names.append(filename)