Tools/freeze/parsesetup.py
# Parse Makefiles and Python Setup(.in) files.

import re


# Extract variable definitions from a Makefile.
# Return a dictionary mapping names to values.
# May raise IOError.

makevardef = re.compile('^([a-zA-Z0-9_]+)[ \t]*=(.*)')

def getmakevars(filename):
    variables = {}
    fp = open(filename)
    pendingline = ""
    try:
        while 1:
            line = fp.readline()
            if pendingline:
                line = pendingline + line
                pendingline = ""
            if not line:
                break
            if line.endswith('\\\n'):
                pendingline = line[:-2]
            matchobj = makevardef.match(line)
            if not matchobj:
                continue
            (name, value) = matchobj.group(1, 2)
            # Strip trailing comment
            i = value.find('#')
            if i >= 0:
                value = value[:i]
            value = value.strip()
            variables[name] = value
    finally:
        fp.close()
    return variables


# Parse a Python Setup(.in) file.
# Return two dictionaries, the first mapping modules to their
# definitions, the second mapping variable names to their values.
# May raise IOError.

setupvardef = re.compile('^([a-zA-Z0-9_]+)=(.*)')

def getsetupinfo(filename):
    modules = {}
    variables = {}
    fp = open(filename)
    pendingline = ""
    try:
        while 1:
            line = fp.readline()
            if pendingline:
                line = pendingline + line
                pendingline = ""
            if not line:
                break
            # Strip comments
            i = line.find('#')
            if i >= 0:
                line = line[:i]
            if line.endswith('\\\n'):
                pendingline = line[:-2]
                continue
            matchobj = setupvardef.match(line)
            if matchobj:
                (name, value) = matchobj.group(1, 2)
                variables[name] = value.strip()
            else:
                words = line.split()
                if words:
                    modules[words[0]] = words[1:]
    finally:
        fp.close()
    return modules, variables


# Test the above functions.

def test():
    import sys
    import os
    if not sys.argv[1:]:
        print 'usage: python parsesetup.py Makefile*|Setup* ...'
        sys.exit(2)
    for arg in sys.argv[1:]:
        base = os.path.basename(arg)
        if base[:8] == 'Makefile':
            print 'Make style parsing:', arg
            v = getmakevars(arg)
            prdict(v)
        elif base[:5] == 'Setup':
            print 'Setup style parsing:', arg
            m, v = getsetupinfo(arg)
            prdict(m)
            prdict(v)
        else:
            print arg, 'is neither a Makefile nor a Setup file'
            print '(name must begin with "Makefile" or "Setup")'

def prdict(d):
    keys = d.keys()
    keys.sort()
    for key in keys:
        value = d[key]
        print "%-15s" % key, str(value)

if __name__ == '__main__':
    test()