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