# 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()