waf

FORK: waf with some random patches
git clone https://git.neptards.moe/neptards/waf.git
Log | Files | Refs | README

fc_scan.py (3089B)


      1 #! /usr/bin/env python
      2 # encoding: utf-8
      3 # DC 2008
      4 # Thomas Nagy 2016-2018 (ita)
      5 
      6 import re
      7 
      8 INC_REGEX = r"""(?:^|['">]\s*;)\s*(?:|#\s*)INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])"""
      9 USE_REGEX = r"""(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)"""
     10 MOD_REGEX = r"""(?:^|;)\s*MODULE(?!\s+(?:PROCEDURE|SUBROUTINE|FUNCTION))\s+(\w+)"""
     11 SMD_REGEX = r"""(?:^|;)\s*SUBMODULE\s*\(([\w:]+)\)\s*(\w+)"""
     12 
     13 re_inc = re.compile(INC_REGEX, re.I)
     14 re_use = re.compile(USE_REGEX, re.I)
     15 re_mod = re.compile(MOD_REGEX, re.I)
     16 re_smd = re.compile(SMD_REGEX, re.I)
     17 
     18 class fortran_parser(object):
     19 	"""
     20 	This parser returns:
     21 
     22 	* the nodes corresponding to the module names to produce
     23 	* the nodes corresponding to the include files used
     24 	* the module names used by the fortran files
     25 	"""
     26 	def __init__(self, incpaths):
     27 		self.seen = []
     28 		"""Files already parsed"""
     29 
     30 		self.nodes = []
     31 		"""List of :py:class:`waflib.Node.Node` representing the dependencies to return"""
     32 
     33 		self.names = []
     34 		"""List of module names to return"""
     35 
     36 		self.incpaths = incpaths
     37 		"""List of :py:class:`waflib.Node.Node` representing the include paths"""
     38 
     39 	def find_deps(self, node):
     40 		"""
     41 		Parses a Fortran file to obtain the dependencies used/provided
     42 
     43 		:param node: fortran file to read
     44 		:type node: :py:class:`waflib.Node.Node`
     45 		:return: lists representing the includes, the modules used, and the modules created by a fortran file
     46 		:rtype: tuple of list of strings
     47 		"""
     48 		txt = node.read()
     49 		incs = []
     50 		uses = []
     51 		mods = []
     52 		for line in txt.splitlines():
     53 			# line by line regexp search? optimize?
     54 			m = re_inc.search(line)
     55 			if m:
     56 				incs.append(m.group(1))
     57 			m = re_use.search(line)
     58 			if m:
     59 				uses.append(m.group(1))
     60 			m = re_mod.search(line)
     61 			if m:
     62 				mods.append(m.group(1))
     63 			m = re_smd.search(line)
     64 			if m:
     65 				uses.append(m.group(1))
     66 				mods.append('{0}:{1}'.format(m.group(1),m.group(2)))
     67 		return (incs, uses, mods)
     68 
     69 	def start(self, node):
     70 		"""
     71 		Start parsing. Use the stack ``self.waiting`` to hold nodes to iterate on
     72 
     73 		:param node: fortran file
     74 		:type node: :py:class:`waflib.Node.Node`
     75 		"""
     76 		self.waiting = [node]
     77 		while self.waiting:
     78 			nd = self.waiting.pop(0)
     79 			self.iter(nd)
     80 
     81 	def iter(self, node):
     82 		"""
     83 		Processes a single file during dependency parsing. Extracts files used
     84 		modules used and modules provided.
     85 		"""
     86 		incs, uses, mods = self.find_deps(node)
     87 		for x in incs:
     88 			if x in self.seen:
     89 				continue
     90 			self.seen.append(x)
     91 			self.tryfind_header(x)
     92 
     93 		for x in uses:
     94 			name = "USE@%s" % x
     95 			if not name in self.names:
     96 				self.names.append(name)
     97 
     98 		for x in mods:
     99 			name = "MOD@%s" % x
    100 			if not name in self.names:
    101 				self.names.append(name)
    102 
    103 	def tryfind_header(self, filename):
    104 		"""
    105 		Adds an include file to the list of nodes to process
    106 
    107 		:param filename: file name
    108 		:type filename: string
    109 		"""
    110 		found = None
    111 		for n in self.incpaths:
    112 			found = n.find_resource(filename)
    113 			if found:
    114 				self.nodes.append(found)
    115 				self.waiting.append(found)
    116 				break
    117 		if not found:
    118 			if not filename in self.names:
    119 				self.names.append(filename)
    120