home *** CD-ROM | disk | FTP | other *** search
/ c't freeware shareware 2001 January / CT_SW0101.ISO / pc / software / kommunik / ftp / kmago112.tgz / kmago112.tar / kmago-1.1.2 / admin / am_edit.py < prev    next >
Text File  |  2001-04-19  |  12KB  |  331 lines

  1. import getopt, string, posixpath, sys, os, os.path, re
  2.  
  3. # Some global globals...
  4. verbose     = 0
  5. thisProg    = posixpath.basename(sys.argv[0])
  6. if not thisProg: # happy only when running in xemacs ;/
  7.     thisProg = 'am_edit.py'
  8. cppsuffixes = ['cpp', 'cc', 'cxx', 'C', 'c++']
  9. hExt        = ['h', 'H', 'hh', 'hxx', 'h++']
  10. progId      = "KDE tags expanded automatically by " + thisProg
  11. use_final   = 1
  12. dryrun      = 0
  13. pathoption  = 0
  14. topdir      = os.path.abspath(os.curdir) + "/"
  15. foreigndirs = []
  16.  
  17. class Makefile:
  18.     def __init__(self, file):
  19.         # some useful globals for the subroutines called here
  20.         self.headerdirs = ['.']
  21.         self.haveAutomocTag   = 0
  22.  
  23.         self.programs = []
  24.  
  25.         # lists the objects compiled into $program
  26.         self.realobjs = {}
  27.         # lists the sources used for $program
  28.         self.sources = {}
  29.         # lists the objects compiled when final
  30.         self.finalObjs = {}
  31.         # the binary name of program variable
  32.         self.realname = {}
  33.         # lists the idl files used for $program
  34.         self.idlfiles = {}
  35.         # lists all idl generated files for cleantarget
  36.         self.idl_output = ""
  37.  
  38.         self.depedmocs = {}
  39.  
  40.         self.dep_files      = ""
  41.         self.dep_finals     = ""
  42.         # the targets to add
  43.         self.target_adds    = {}
  44.         self.kdelang        = ""
  45.         self.makefile       = file
  46.         self.makefileDir    = os.path.dirname(self.makefile)
  47.         self.options        = {}
  48.  
  49.  
  50.     NoMakefileAmFound = "found Makefile.in without Makefile.am"
  51.  
  52.     def findLine(self, line):
  53.         import types
  54.         if type(line) is types.StringType:
  55.             regexp = re.compile(line)
  56.         else:
  57.             regexp = line
  58.         for line in self.lines:
  59.             match = regexp.match(line)
  60.             if match:
  61.                 return match
  62.     
  63.     def substituteLine(self, old, new):
  64.         import types
  65.         if type(old) is types.StringType:
  66.             regexp = re.compile(old)
  67.         else:
  68.             regexp = old
  69.             
  70.         for index in range(len(self.lines)):
  71.             line = self.lines[index]
  72.             match = regexp.match(line)
  73.             if match:
  74.                 line = '#>- ' + line
  75.                 newlines = string.split(new, '\n')
  76.                 self.lines[index:index+1] = [line, '#>+ %d' % len(newlines)] + newlines
  77.                 return
  78.  
  79.     def addTarget(self, target, dependson):
  80.         if not self.target_adds.has_key(target):
  81.             self.target_adds[target] = [dependson]
  82.         else:
  83.             self.target_adds[target].append(dependson)
  84.             
  85.     def appendLines(self, newlines):
  86.         lines = string.split(newlines, '\n') + ['\n']
  87.         self.lines.extend(['#>+ %d' % len(lines)] + lines)
  88.         
  89.     def restore(self):
  90.         index = 0
  91.         while index < len(self.lines):
  92.             line = self.lines[index]
  93.             if line[0:3] == '#>+':
  94.                 # the +1 is the comment itself
  95.                 linec = string.atoi(line[3:]) + 1
  96.                 del self.lines[index:index+linec]
  97.                 continue
  98.             if line[0:3] == '#>-':
  99.                 self.lines[index] = self.lines[index][4:]
  100.             index = index + 1
  101.         
  102.     def initialize(self):
  103.         global foreigndirs
  104.  
  105.         os.chdir(self.makefileDir)
  106.         self.printname = string.replace(self.makefile, topdir, "")
  107.         self.makefile = os.path.basename(self.makefile)
  108.  
  109.         if not posixpath.exists("Makefile.am"):
  110.             raise self.NoMakefileAmFound, self.makefileDir
  111.  
  112.         for dir in foreigndirs:
  113.             if dir.match(self.makefileDir):
  114.                 print 'leaving ' + self.makefileDir
  115.                 return 0
  116.  
  117.         f = open(self.makefile)
  118.         self.lines = []
  119.       
  120.         while 1:
  121.             line = f.readline()
  122.             if not line: break
  123.             self.lines.append(string.rstrip(line))
  124.  
  125.         f.close()
  126.         
  127.         # take out the 
  128.         self.restore()
  129.         
  130.         optionline = re.compile('^\s*(\w+)\s*=\s*([^\n]*)$')
  131.         linecontinued = re.compile('\\\s*\n')
  132.         lastline = ''
  133.  
  134.         index = 0
  135.         while index < len(self.lines):
  136.             line = self.lines[index]
  137.             if linecontinued.search(line):
  138.                 self.lines[index] = linecontinued.sub(' ', line) + self.lines[index+1]
  139.                 continue
  140.             else:
  141.                 index = index + 1
  142.  
  143.             match = optionline.search(line)
  144.             if match:
  145.                 self.options[match.group(1)] = match.group(2)
  146.  
  147.         if self.options.has_key('KDE_OPTIONS'):
  148.             options = string.split(self.options['KDE_OPTIONS'])
  149.             if 'foreign' in options:
  150.                 foreigndirs.append(re.compile(self.makefileDir + "/.*"))
  151.                 return 0
  152.  
  153.         self.cxxsuffix = ""
  154.         suffixes = re.compile('^\.SUFFIXES:(.*)$')
  155.  
  156.         for line in self.lines:
  157.             match = suffixes.match(line)
  158.             if match:
  159.                 existing_suffixes = string.split(match.group(1))
  160.                 for suffix in existing_suffixes:
  161.                     # leave out the .
  162.                     if suffix[1:] in cppsuffixes:
  163.                         self.cxxsuffix = suffix[1:]
  164.                         break
  165.                 if self.cxxsuffix:
  166.                     break
  167.  
  168.         search_real_programs = {}
  169.  
  170.         for option in self.options.keys():
  171.             if string.rfind(option, '_OBJECTS') > 0:
  172.  
  173.                 program = option[0:string.find(option, '_OBJECTS')]
  174.                 objs = self.options[option]
  175.  
  176.                 variable_in_objects = 0
  177.  
  178.                 objlist = string.split(objs)
  179.                 variable = re.compile('\$\((\w+)\)')
  180.                 for obj in objlist:
  181.                     match = variable.match(obj)
  182.                     if match and not match.group(1) == 'OBJEXT':
  183.                         variable_in_objects = 1
  184.                         break
  185.  
  186.                 if variable_in_objects:
  187.                     continue
  188.  
  189.                 if len(program) > 3 and program[3] == 'am_':
  190.                     program = program[3:]
  191.  
  192.                 if verbose:
  193.                     print "found program " + program
  194.  
  195.                 self.programs.append(program)
  196.                 self.realobjs[program] = objs
  197.  
  198.                 if self.options.has_key(program + "_SOURCES"):
  199.                     self.sources[program] = self.options[program + "_SOURCES"]
  200.                 else:
  201.                     self.sources[program] = ""
  202.                     sys.stderr.write("found program with no _SOURCES: " + program + '\n')
  203.  
  204.                 # unmask to regexp
  205.                 realprogram = string.replace(program, '_', '.')
  206.                 search_real_programs[program] = re.compile('.*(' + realprogram +
  207.                                                            ')(\$\(EXEEXT\)?)?:.*\$\(' +
  208.                                                            program + '_OBJECTS\).*')
  209.  
  210.                 self.realname[program] = "";
  211.  
  212.         for line in self.lines:
  213.             if string.find(line, '_OBJECTS') > 0: # just a random piece to not use at _every_ line
  214.                 for program in self.programs:
  215.                     match = search_real_programs[program].match(line)
  216.                     if match:
  217.                         self.realname[program] = match.group(1)
  218.  
  219.     def finalTouch(self):
  220.         if self.options.has_key('DEPDIR'):
  221.             sys.stderr.write(self.printname + " defines DEPDIR. This means you're using automake > 1.4 - this is not supported!")
  222.         else:
  223.             # taken out a random variable
  224.             self.substituteLine('bindir\s*=.*', 'DEPDIR = .deps\nbindir = ' + self.options['bindir'])
  225.  
  226.         self.appendLines('cvs-clean:\n' +
  227.                          '\t$(MAKE) -f $(top_srcdir)/admin/Makefile.common cvs-clean')
  228.  
  229.         self.appendLines('kde-rpo-clean:\n'+
  230.                          '\t-rm -f *.rpo')
  231.  
  232.         self.addTarget('clean', 'kde-rpo-clean')
  233.         self.addAllTargets()
  234.  
  235.     def addAllTargets(self):
  236.         for target in self.target_adds.keys():
  237.             match = self.findLine(target + ':\s*(.*)')
  238.             if match:
  239.                 self.substituteLine(match.re, target + ': ' +
  240.                                     string.join(self.target_adds[target]) +
  241.                                     ' ' + match.group(1))
  242.                     
  243.     def writeback(self):
  244.         f = open(self.makefile, 'w')
  245.         for line in self.lines:
  246.             f.write(line)
  247.             f.write('\n')
  248.         f.close()
  249.  
  250.     def tag_automake(self):
  251.         match = self.findLine('^(.*cd \$\(top_srcdir\)\s+&&\s+\$\(AUTOMAKE\).*)$')
  252.         if not match: return 1
  253.         self.substituteLine(match.re, match.group(1) + '\n' +
  254.                        '\tcd $(top_srcdir) && python ' +
  255.                        thisProg + ' ' + self.printname)
  256.         
  257. def main():
  258.     global use_final, dryrun, pathoption, thisProg, verbose
  259.  
  260.     optlist, makefiles = getopt.getopt(sys.argv[1:], 'vhp:n', [
  261.         'version', 'verbose', 'path=', 'help', 'no-final'])
  262.  
  263.     for option, param in optlist:
  264.         if option == '--version':
  265.             print "\n"
  266.             print thisProg + "$Revision: 1.3 $"
  267.             print "This is really free software, unencumbered by the GPL."
  268.             print "You can do anything you like with it except sueing me."
  269.             print "Copyright 1998 Kalle Dalheimer <kalle\@kde.org>"
  270.             print "Concept, design and unnecessary questions about perl"
  271.             print "     by Matthias Ettrich <ettrich\@kde.org>"
  272.             print ""
  273.             print "Making it useful by Stephan Kulow <coolo\@kde.org> and"
  274.             print "Harri Porten <porten\@kde.org>"
  275.             print "Updated (Feb-1999), John Birch <jb.nz\@writeme.com>"
  276.             print "Current Maintainer Stephan Kulow"
  277.             sys.exit(0)
  278.         if option == '--verbose' or option == '-v':
  279.             verbose = 1
  280.         if option == '-p' or option == '--path':
  281.             thisProg = param + "/" + thisProg
  282.             if (not posixpath.exists(thisProg)):
  283.                 sys.stderr.write(thisProg + " doesn't exist\n")
  284.             pathoption=1
  285.         if option == '--help' or option == '-h':
  286.             print "Usage " + thisProg + " [OPTION] ... [dir/Makefile.in]..."
  287.             print "Patches dir/Makefile.in generated from automake"
  288.             print "(where dir can be a full or relative directory name)"
  289.             print "  -v, --verbose      verbosely list files processed"
  290.             print "  -h, --help         print this help, then exit"
  291.             print "  --version          print version number, then exit"
  292.             print "  -p, --path=        use the path to am_edit if the path"
  293.             print "  --no-final         don't patch for --enable-final"
  294.             print "                     called from is not the one to be used"
  295.             sys.exit(0)
  296.         if option == '--no-final':
  297.             use_final = 0
  298.         if option == '-n':
  299.             dryrun = 1
  300.  
  301.     if not use_final:
  302.         thisProg = thisProg + " --no-final"
  303.  
  304.     if thisProg[0] == '/' and not pathoption:
  305.         sys.stderr.write( "Illegal full pathname call performed...\n"
  306.                           "The call to \"" + thisProg + "\"\n"
  307.                           "would be inserted in some Makefile.in.\n"
  308.                           "Please use option --path.\n")
  309.         sys.exit(1)
  310.  
  311.     if len(makefiles) == 0:
  312.         import find
  313.         makefiles = find.find('Makefile.in')
  314.  
  315.     for index in range(len(makefiles)):
  316.         if not makefiles[index][0] == '/':
  317.             makefiles[index] = os.path.normcase(os.path.abspath(makefiles[index]))
  318.  
  319.     makefiles.sort()
  320.     for file in makefiles:
  321.         makefile = Makefile(file)
  322.         try:
  323.             makefile.initialize()
  324.             makefile.tag_automake()
  325.             makefile.finalTouch()
  326.             makefile.writeback()
  327.         except Makefile.NoMakefileAmFound, param:
  328.             if verbose: print Makefile.NoMakefileAmFound + ' in ' + param
  329.  
  330. main()
  331.