import getopt, string, posixpath, sys, os, os.path, re # Some global globals... verbose = 0 thisProg = posixpath.basename(sys.argv[0]) if not thisProg: # happy only when running in xemacs ;/ thisProg = 'am_edit.py' cppsuffixes = ['cpp', 'cc', 'cxx', 'C', 'c++'] hExt = ['h', 'H', 'hh', 'hxx', 'h++'] progId = "KDE tags expanded automatically by " + thisProg use_final = 1 dryrun = 0 pathoption = 0 topdir = os.path.abspath(os.curdir) + "/" foreigndirs = [] class Makefile: def __init__(self, file): # some useful globals for the subroutines called here self.headerdirs = ['.'] self.haveAutomocTag = 0 self.programs = [] # lists the objects compiled into $program self.realobjs = {} # lists the sources used for $program self.sources = {} # lists the objects compiled when final self.finalObjs = {} # the binary name of program variable self.realname = {} # lists the idl files used for $program self.idlfiles = {} # lists all idl generated files for cleantarget self.idl_output = "" self.depedmocs = {} self.dep_files = "" self.dep_finals = "" # the targets to add self.target_adds = {} self.kdelang = "" self.makefile = file self.makefileDir = os.path.dirname(self.makefile) self.options = {} NoMakefileAmFound = "found Makefile.in without Makefile.am" def findLine(self, line): import types if type(line) is types.StringType: regexp = re.compile(line) else: regexp = line for line in self.lines: match = regexp.match(line) if match: return match def substituteLine(self, old, new): import types if type(old) is types.StringType: regexp = re.compile(old) else: regexp = old for index in range(len(self.lines)): line = self.lines[index] match = regexp.match(line) if match: line = '#>- ' + line newlines = string.split(new, '\n') self.lines[index:index+1] = [line, '#>+ %d' % len(newlines)] + newlines return def addTarget(self, target, dependson): if not self.target_adds.has_key(target): self.target_adds[target] = [dependson] else: self.target_adds[target].append(dependson) def appendLines(self, newlines): lines = string.split(newlines, '\n') + ['\n'] self.lines.extend(['#>+ %d' % len(lines)] + lines) def restore(self): index = 0 while index < len(self.lines): line = self.lines[index] if line[0:3] == '#>+': # the +1 is the comment itself linec = string.atoi(line[3:]) + 1 del self.lines[index:index+linec] continue if line[0:3] == '#>-': self.lines[index] = self.lines[index][4:] index = index + 1 def initialize(self): global foreigndirs os.chdir(self.makefileDir) self.printname = string.replace(self.makefile, topdir, "") self.makefile = os.path.basename(self.makefile) if not posixpath.exists("Makefile.am"): raise self.NoMakefileAmFound, self.makefileDir for dir in foreigndirs: if dir.match(self.makefileDir): print 'leaving ' + self.makefileDir return 0 f = open(self.makefile) self.lines = [] while 1: line = f.readline() if not line: break self.lines.append(string.rstrip(line)) f.close() # take out the self.restore() optionline = re.compile('^\s*(\w+)\s*=\s*([^\n]*)$') linecontinued = re.compile('\\\s*\n') lastline = '' index = 0 while index < len(self.lines): line = self.lines[index] if linecontinued.search(line): self.lines[index] = linecontinued.sub(' ', line) + self.lines[index+1] continue else: index = index + 1 match = optionline.search(line) if match: self.options[match.group(1)] = match.group(2) if self.options.has_key('KDE_OPTIONS'): options = string.split(self.options['KDE_OPTIONS']) if 'foreign' in options: foreigndirs.append(re.compile(self.makefileDir + "/.*")) return 0 self.cxxsuffix = "" suffixes = re.compile('^\.SUFFIXES:(.*)$') for line in self.lines: match = suffixes.match(line) if match: existing_suffixes = string.split(match.group(1)) for suffix in existing_suffixes: # leave out the . if suffix[1:] in cppsuffixes: self.cxxsuffix = suffix[1:] break if self.cxxsuffix: break search_real_programs = {} for option in self.options.keys(): if string.rfind(option, '_OBJECTS') > 0: program = option[0:string.find(option, '_OBJECTS')] objs = self.options[option] variable_in_objects = 0 objlist = string.split(objs) variable = re.compile('\$\((\w+)\)') for obj in objlist: match = variable.match(obj) if match and not match.group(1) == 'OBJEXT': variable_in_objects = 1 break if variable_in_objects: continue if len(program) > 3 and program[3] == 'am_': program = program[3:] if verbose: print "found program " + program self.programs.append(program) self.realobjs[program] = objs if self.options.has_key(program + "_SOURCES"): self.sources[program] = self.options[program + "_SOURCES"] else: self.sources[program] = "" sys.stderr.write("found program with no _SOURCES: " + program + '\n') # unmask to regexp realprogram = string.replace(program, '_', '.') search_real_programs[program] = re.compile('.*(' + realprogram + ')(\$\(EXEEXT\)?)?:.*\$\(' + program + '_OBJECTS\).*') self.realname[program] = ""; for line in self.lines: if string.find(line, '_OBJECTS') > 0: # just a random piece to not use at _every_ line for program in self.programs: match = search_real_programs[program].match(line) if match: self.realname[program] = match.group(1) def finalTouch(self): if self.options.has_key('DEPDIR'): sys.stderr.write(self.printname + " defines DEPDIR. This means you're using automake > 1.4 - this is not supported!") else: # taken out a random variable self.substituteLine('bindir\s*=.*', 'DEPDIR = .deps\nbindir = ' + self.options['bindir']) self.appendLines('cvs-clean:\n' + '\t$(MAKE) -f $(top_srcdir)/admin/Makefile.common cvs-clean') self.appendLines('kde-rpo-clean:\n'+ '\t-rm -f *.rpo') self.addTarget('clean', 'kde-rpo-clean') self.addAllTargets() def addAllTargets(self): for target in self.target_adds.keys(): match = self.findLine(target + ':\s*(.*)') if match: self.substituteLine(match.re, target + ': ' + string.join(self.target_adds[target]) + ' ' + match.group(1)) def writeback(self): f = open(self.makefile, 'w') for line in self.lines: f.write(line) f.write('\n') f.close() def tag_automake(self): match = self.findLine('^(.*cd \$\(top_srcdir\)\s+&&\s+\$\(AUTOMAKE\).*)$') if not match: return 1 self.substituteLine(match.re, match.group(1) + '\n' + '\tcd $(top_srcdir) && python ' + thisProg + ' ' + self.printname) def main(): global use_final, dryrun, pathoption, thisProg, verbose optlist, makefiles = getopt.getopt(sys.argv[1:], 'vhp:n', [ 'version', 'verbose', 'path=', 'help', 'no-final']) for option, param in optlist: if option == '--version': print "\n" print thisProg + "$Revision: 1.2 $" print "This is really free software, unencumbered by the GPL." print "You can do anything you like with it except sueing me." print "Copyright 1998 Kalle Dalheimer " print "Concept, design and unnecessary questions about perl" print " by Matthias Ettrich " print "" print "Making it useful by Stephan Kulow and" print "Harri Porten " print "Updated (Feb-1999), John Birch " print "Current Maintainer Stephan Kulow" sys.exit(0) if option == '--verbose' or option == '-v': verbose = 1 if option == '-p' or option == '--path': thisProg = param + "/" + thisProg if (not posixpath.exists(thisProg)): sys.stderr.write(thisProg + " doesn't exist\n") pathoption=1 if option == '--help' or option == '-h': print "Usage " + thisProg + " [OPTION] ... [dir/Makefile.in]..." print "Patches dir/Makefile.in generated from automake" print "(where dir can be a full or relative directory name)" print " -v, --verbose verbosely list files processed" print " -h, --help print this help, then exit" print " --version print version number, then exit" print " -p, --path= use the path to am_edit if the path" print " --no-final don't patch for --enable-final" print " called from is not the one to be used" sys.exit(0) if option == '--no-final': use_final = 0 if option == '-n': dryrun = 1 if not use_final: thisProg = thisProg + " --no-final" if thisProg[0] == '/' and not pathoption: sys.stderr.write( "Illegal full pathname call performed...\n" "The call to \"" + thisProg + "\"\n" "would be inserted in some Makefile.in.\n" "Please use option --path.\n") sys.exit(1) if len(makefiles) == 0: import find makefiles = find.find('Makefile.in') for index in range(len(makefiles)): if not makefiles[index][0] == '/': makefiles[index] = os.path.normcase(os.path.abspath(makefiles[index])) makefiles.sort() for file in makefiles: makefile = Makefile(file) try: makefile.initialize() makefile.tag_automake() makefile.finalTouch() makefile.writeback() except Makefile.NoMakefileAmFound, param: if verbose: print Makefile.NoMakefileAmFound + ' in ' + param main()