1# Parse Makefiles and Python Setup(.in) files.
2
3import re
4
5
6# Extract variable definitions from a Makefile.
7# Return a dictionary mapping names to values.
8# May raise IOError.
9
10makevardef = re.compile('^([a-zA-Z0-9_]+)[ \t]*=(.*)')
11
12def getmakevars(filename):
13    variables = {}
14    fp = open(filename)
15    pendingline = ""
16    try:
17        while 1:
18            line = fp.readline()
19            if pendingline:
20                line = pendingline + line
21                pendingline = ""
22            if not line:
23                break
24            if line.endswith('\\\n'):
25                pendingline = line[:-2]
26            matchobj = makevardef.match(line)
27            if not matchobj:
28                continue
29            (name, value) = matchobj.group(1, 2)
30            # Strip trailing comment
31            i = value.find('#')
32            if i >= 0:
33                value = value[:i]
34            value = value.strip()
35            variables[name] = value
36    finally:
37        fp.close()
38    return variables
39
40
41# Parse a Python Setup(.in) file.
42# Return two dictionaries, the first mapping modules to their
43# definitions, the second mapping variable names to their values.
44# May raise IOError.
45
46setupvardef = re.compile('^([a-zA-Z0-9_]+)=(.*)')
47
48def getsetupinfo(filename):
49    modules = {}
50    variables = {}
51    fp = open(filename)
52    pendingline = ""
53    try:
54        while 1:
55            line = fp.readline()
56            if pendingline:
57                line = pendingline + line
58                pendingline = ""
59            if not line:
60                break
61            # Strip comments
62            i = line.find('#')
63            if i >= 0:
64                line = line[:i]
65            if line.endswith('\\\n'):
66                pendingline = line[:-2]
67                continue
68            matchobj = setupvardef.match(line)
69            if matchobj:
70                (name, value) = matchobj.group(1, 2)
71                variables[name] = value.strip()
72            else:
73                words = line.split()
74                if words:
75                    modules[words[0]] = words[1:]
76    finally:
77        fp.close()
78    return modules, variables
79
80
81# Test the above functions.
82
83def test():
84    import sys
85    import os
86    if not sys.argv[1:]:
87        print('usage: python parsesetup.py Makefile*|Setup* ...')
88        sys.exit(2)
89    for arg in sys.argv[1:]:
90        base = os.path.basename(arg)
91        if base[:8] == 'Makefile':
92            print('Make style parsing:', arg)
93            v = getmakevars(arg)
94            prdict(v)
95        elif base[:5] == 'Setup':
96            print('Setup style parsing:', arg)
97            m, v = getsetupinfo(arg)
98            prdict(m)
99            prdict(v)
100        else:
101            print(arg, 'is neither a Makefile nor a Setup file')
102            print('(name must begin with "Makefile" or "Setup")')
103
104def prdict(d):
105    keys = sorted(d.keys())
106    for key in keys:
107        value = d[key]
108        print("%-15s" % key, str(value))
109
110if __name__ == '__main__':
111    test()
112