#! /usr/bin/env python

import string, re, os, types

from utilities import variablere, variablesre, extre, definere, cppext, hext, print_error
import utilities
from handlerbase import register_handler
import handlerbase
from target import Target, PhonyConflict
import program

class MakeFile:
	def __init__(self, filename):
		self.targets = {}
		self.defs = {}
		self.printed_defs = {}
		self.conds = {}
		self.dep_files = []
		self.parent = None
		self.filename = filename[ len(utilities._topsrcdir) + 1: ]
		self.subdirs = []
		self.configure_files = []

		# these variables are expected to used from the environment
		# and not from configure
		self.environment_variables = ["DESTDIR", "podir", "EXTRACTRC",
									  "QTDIR", "PREPARETIPS", "MAKE",
									  "INSTALL_STRIP_FLAG", "INSTALL_PROGRAM_ENV",
									  "transform", "AM_MAKEFLAGS", "MAKEFLAGS"]
		# these variables come from configure but are handled if the
		# Makefiles overwrites them
		self.handled_overwrites = ["LDFLAGS", "CPPFLAGS", "CFLAGS", "YFLAGS", "LFLAGS",
								   "datadir", "LEX_OUTPUT_ROOT"]
		
	def insertTarget(self, target, deps, rules = [], user_specified=0, phony=0):
		# throws error if a line doesn't start with <tab>
		t = Target(target, deps, rules, user_specified, phony)
		if self.targets.has_key(target):
			# throws if both have rules
			try:
				self.targets[target].merge(t)
			except PhonyConflict:
				utilities.print_error("%s tries to overwrite the PHONY status of %s\n" % (self.filename, target))
		else:
			self.targets[target] = t

	# the one for the rules - overwritten in AMFile
	def set_def_printed(self, definition):
		if self.printed_defs.has_key(definition):
			print '%s: %s already defined' % (self.filename, definition)
		self.printed_defs[definition] = 1
		# if the parent is not defined, it's not tragic
		if self.parent:
			self.parent.set_def_printed(definition)
		
	def print_out_definition(self, output, definition):
		if self.printed_defs.has_key(definition):
			return
		self.set_def_printed(definition)
			
		if not self.is_defined(definition):
			print '%s: %s is not defined but used' % (self.filename, definition)
			return

		if self.defs.has_key(definition):
			for var in self.defs[definition]:
				match = variablere.match(var)
				if match:
					self.print_out_definition(output, match.group(1))
			rhs = string.join(self.defs[definition])
		
			output.append('%s = %s\n' % (definition, rhs))
		else:
			tuple = self.conds[definition]
			for var in tuple[1] + tuple[2]:
				match = variablere.match(var)
				if match:
					self.print_out_definition(output, match.group(1))

			output.append('@%s_TRUE@%s = %s\n' % (tuple[0], definition,
												  string.join(tuple[1])))
			output.append('@%s_FALSE@%s = %s\n' % (tuple[0], definition,
												   string.join(tuple[2])))

	def print_out_target(self, output, target):
		defs = self.targets[target].used_defines()
		for definition in defs:
			self.print_out_definition(output, definition)
		self.targets[target].print_out(output)

	def print_out_include(self, output, subdir, cond):
		prefix = self.canon_subdir + "_" + utilities.canon_name(subdir)
		output.append( cond + prefix + "_srcdir = " + self.source + subdir + "\n")
		output.append( cond + prefix + "_builddir = " + self.build + subdir + "\n")
		self.printed_defs[prefix + "_srcdir"] = 1
		self.printed_defs[prefix + "_builddir"] = 1
		output.append( cond + "@am__include@ @am__quote@%s%s/Makefile.rules@am__quote@\n" %
					   (self.build, subdir))
		output.append( cond + "@am__include@ @am__quote@%s%s/Makefile.calls@am__quote@\n" %
					   (self.build, subdir))
						  
	def print_out(self, output):

		output.append("# This is the first line, so the second doesn't look ugly\n");
		for dep in self.dep_files:
			output.append("@am__include@ @am__quote@%s%s@am__quote@\n" % (self.build, dep))
		output.append("\n")
	
		for var in subst_vars.keys() + self.environment_variables:
			self.printed_defs[var] = 1

		# these are the variables the toplevel Makefile _has_ to write
		self.printed_defs[self.canon_subdir + "_srcdir"] = 1
		self.printed_defs[self.canon_subdir + "_builddir"] = 1
		self.printed_defs["DEPDIR"] = 1

		for subdir in self.subdirs:
			if subdir != '.':
				match = variablere.match(subdir)
				
				if match:
					self.print_out_definition(output, match.group(1))
					assert(self.conds.has_key(match.group(1)))
					tuple = self.conds[match.group(1)]
					for dir in tuple[1]:
						self.print_out_include(output, dir, "@%s_TRUE@" % tuple[0])
					for dir in tuple[2]:
						self.print_out_include(output, dir, "@%s_FALSE@" % tuple[0])
				else:
					self.print_out_include(output, subdir, "")
				output.append("\n")
		
		keys = self.targets.keys()
		keys.sort()
		for key in keys:
			if not key == "all":
				self.print_out_target(output, key)

		output.append('\n')
		output.append('# the following defines are only there for reference\n')
		keys = self.defines()
		keys.sort()
		for definition in keys:
			self.print_out_definition(output, definition)
		
	def target(self, target):
		try:
			return self.targets[target]
		except:
			return None

	def defines(self):
		return self.defs.keys() + self.conds.keys()
	
	def is_target(self, target):
		return self.targets.has_key(target)
	
	def is_defined(self, variable):
		return self.defs.has_key(variable) or self.conds.has_key(variable)

	def del_define(self, variable):
		#return self.defs.remove(variable)
		if self.defs.has_key(variable):
			del self.defs[variable]

	def add_define(self, variable, value, cond = "", cond_true=1):
		if type(value) == types.StringType:
			list = string.split(string.strip(string.replace(value, '\001', ' ')))
			if not len(value) and not variable in self.handled_overwrites:
				# if we get a paranoid option, we can enable it again
			    # sys.stderr.write("%s defines empty %s\n" % (self.filename, variable))
				pass
		else:
			list = value

		if not len(cond):
			if self.defs.has_key(variable):
				if value in self.defs[variable]:
					# debug
					print '%s: %s is already in define %s (should not happen)' % (self.filename, value,
																				  variable)
					return
				self.defs[variable].extend(list)
			else:
				self.defs[variable] = list
		else:
			if cond_true:
				if self.conds.has_key(variable):
					print '%s: %s is redefined in automake conditional' % (self.filename,
																		   variable)
				self.conds[variable] = (cond, list, [])
			else:
				if not self.conds.has_key(variable):
					self.conds[variable] = (cond, [], list)
				if not self.conds[variable][0] == cond:
					print_error('%s: %s defined in two different conditionals\n' % (self.filename,
																						 variable))
					return
				tuple = self.conds[variable]
				self.conds[variable] = (tuple[0], tuple[1], list)

	def _var_rec_var(self, str):
		if not len(str):
			return ['']
		
		val = variablesre.match(str)
		if val:
			if not len(val.group(1)) and not len(val.group(3)):
				return self._var_rec_priv_(val.group(2))
			else:
				ret = self._var_rec_priv_(val.group(2))
				if len(ret) > 1:
					print_error('%s: variable \'%s\' is used in another variable, but contains a list\n' % (self.filename, val.group(2)))
					return [str]
				if not len(ret):
					return [str]

				suffix = self._var_rec_var(val.group(3))
				prefix = self._var_rec_var(val.group(1))
				assert(len(prefix) == 1)
				assert(len(suffix) == 1)
				retstr = prefix[0] + ret[0] + suffix[0]

				if subst_vars.has_key(val.group(2)):
					return [retstr]
				else:
					return self._var_rec_var(retstr)
		else:
			if str[0] == '@' and str[-1] == '@':
				# we don't know the content of this autoconf variable,
				# so take it as empty.
				# We should check, if we have an AC_SUBST defined var
				# of this name - but first I need a test case
				print_error("%s: %s seems to be a autoconf define\n" %
								 (self.filename, str))
				return [str]
		return [str]
					
	def _var_rec_priv_(self, variable):

		var_list = self.definition(variable)
		if not len(var_list):
			if variable in subst_vars.keys() or self.conds.has_key(variable):
				return ["$(%s)" % variable]
			else:
				return []

		return_list = []
		
		if self.circle.has_key(variable):
			sys.stderr.write("Warning: %s produces a circle.\n" % variable)
			return return_list

		self.circle[variable] = 1
	
		for entry in var_list:
			return_list.extend(self._var_rec_var(entry))

		del self.circle[variable]
		return return_list

	def definition(self, variable):
		if self.defs.has_key(variable):
			return self.defs[variable]
		else:
			if variable in subst_vars.keys() or self.conds.has_key(variable):
				return []
			sys.stderr.write('%s: %s not defined\n' % (self.filename, variable))
			return []
		
	def value_of(self, variable):
		if self.defs.has_key(variable):
			return string.join(self.defs[variable])
		return None

	def value_list(self, variable):
		if self.defs.has_key(variable):
			return self.definition_rec(variable)
		return []

	def definition_rec(self, variable):
		self.circle = {}
		ret = self._var_rec_priv_(variable)
		del self.circle
		return ret
	
	def set_configure_files(self, files):
		for file in files:
			if not file in self.configure_files:
				self.configure_files.append(file)
			prefix = self.build
			if self.subdir == '.':
				prefix = ""
			self.insertTarget(prefix + file, ['$(top_builddir)/config.status',
												  self.source + file + '.in'],
							  ["cd $(top_builddir) && " +
							   "CONFIG_FILES=%s/%s " % (self.subdir, file) + 
							   "CONFIG_HEADERS= "
							   "CONFIG_LINKS= $(SHELL) ./config.status"])
			
	def set_configure_headers(self, files):
		assert(len(files) == 1) # we need to enumerate stamp-h then
		for file in files:
			self.insertTarget(self.build + file, self.build + 'stamp-h',
									['@if test ! -f %s; then \\' % (self.build + file),
									 '   rm -f %sstamp-h; \\' % self.build,
									 '   cd %s && $(MAKE) stamp-h; \\' % self.build,
									 'else :; fi'])

			config_status_argument = '%s/%s' % (self.subdir, file)
			if self.subdir == '.':
				config_status_argument = file
				
			self.insertTarget(self.build + 'stamp-h',
									[self.source + file + '.in',
									 '$(top_builddir)/config.status'],
									['@rm -f %sstamp-h' % self.build,
									 'cd $(top_builddir) && $(SHELL) ./config.status %s' % config_status_argument])

			self.insertTarget(self.build + file + '.in', ['$(top_srcdir)/configure.in'],
									['cd $(top_srcdir) && $(AUTOHEADER)',
									 'touch ' + self.source + file + '.in'])

			self.insertTarget('distclean-hdr-%s' % self.canon_subdir, [],
									'-rm -f ' + self.build + file + ' ' + self.build + 'stamp-h', phony=1)
			self.insertTarget('distclean', 'distclean-hdr-%s' % self.canon_subdir, phony=1)
	
	def final_reorder(self):
		self.insertTarget('.SUFFIXES', '')
		for target in self.targets.values():
			if target.is_phony and not target.target == '.PHONY':
				self.insertTarget('.PHONY', target.target, phony=1)
	
class AMFile(MakeFile):
	def __init__(self, filename):
		MakeFile.__init__(self, filename)
		self.commentre = re.compile('\s*#.*')
		self.objs = []
		self.ui_files = {}
		self.rulef = MakeFile(filename[:-3] + '.rules')
		self.callf = MakeFile(filename[:-3] + '.calls')
		self.to_handle_targets = []
		self.am_includes = []
		self.binaries = {}
		self.mansectre = re.compile('.*\.([0-9nl])[a-z]*')
		self.mansections = ['0','1','2','3','4','5','6','7','8','9','n','l']
		
		if len(filename):
			self.parse(filename)
			
		self.default_includes = string.join(self.replace_srcdir(['$(DEFS)', '-I.', '-I$(srcdir)', '-I$(top_builddir)']))
		self.defs['DEFAULT_INCLUDES'] = ['-I.', '-I$(srcdir)', '-I$(top_builddir)']

		self.insertTarget("force-reedit", [],
						  ["cd $(top_srcdir) && UNSERMAKE=\"%s\" %s %s/Makefile" % (os.environ['UNSERMAKE'], os.environ['UNSERMAKE'], self.subdir)], phony=1)
                self.insertTarget("force-install", [],
                	['@$(MAKE) install UNSERMAKE_FORCE_INSTALL=FORCE'], phony=1)
                self.insertTarget("force-install-am", [],
                	['@$(MAKE) install-am UNSERMAKE_FORCE_INSTALL=FORCE'], phony=1)
                self.insertTarget("FORCE", [], phony=1)

		self.rulef.insertTarget("all-recursive", "all-am-%s" % (self.canon_subdir), phony=1)
		self.insertTarget("all-am", "all-am-%s" % (self.canon_subdir), phony=1)
		self.insertTarget("all", "all-recursive", phony=1)
		self.insertTarget("all-recursive", [], phony=1)
		self.insertTarget("install-am", "install-am-%s" % (self.canon_subdir), phony=1)
                
	def read_in(self, filename):
		# read the file
		lines = open(filename, 'r').readlines()
		ret = []
		for line in lines:
			if line.startswith('include '):
				line = string.strip(line[8:])
				if line.startswith('$(top_srcdir)'):
					dir = os.path.dirname( filename[ len(utilities._topsrcdir) + 1: ])
					if len(dir):
						slashes = string.count(dir, '/')
						topdir = '..'
						for h in range(slashes):
							topdir = topdir + '/..'
						line = topdir + '/' + line[14:]
					else:
						line = line[14:]
				file = os.path.join(os.path.dirname(filename), line)
				ret.extend(self.read_in(file))
				self.am_includes.append(line)
			else:
				ret.append(line)
		return ret
		
	def parse(self, filename):
		self.lines = self.read_in(filename)
		self.dirname = os.path.dirname(filename)
		self.subdir = os.path.dirname(self.filename)
	
		if not len(self.subdir):
			self.subdir = '.'
			self.canon_subdir = 'top'
		else:
			self.canon_subdir = 'top_' + utilities.canon_name(self.subdir)
			
		# sharing some variables
		self.rulef.source = '$(%s_srcdir)/' % self.canon_subdir
		self.rulef.build = '$(%s_builddir)/' % self.canon_subdir
		self.rulef.subdir = self.subdir
		self.rulef.canon_subdir = self.canon_subdir
		
		self.source = self.rulef.source
		self.build = self.rulef.build
		
		self.callf.source = self.rulef.source
		self.callf.build = self.rulef.build
		self.callf.subdir = self.rulef.subdir
		self.callf.canon_subdir = self.rulef.canon_subdir
		
		# add a final line feed to be sure we have it
		if len(self.lines) == 0:
			self.lines = ["\n"]
		if not self.lines[-1][-1] == '\n':
			self.lines.append('\n')

		# concatinate lines with backslash (replaced with \001 for later
		# reference). Automake comments are skiped
		index = 0
		ebre = re.compile('\\\[ \t]*\n')
		while index < len(self.lines):
			if self.lines[index].startswith('##'):
				del self.lines[index]
				continue
			if ebre.search(self.lines[index]):
				self.lines[index:index+2] = [ ebre.sub('\001', self.lines[index], 1) + self.lines[index + 1] ] 
			else:
				index = index + 1

		self.find_targets()
		self.find_defines()
		self.find_opts()
		
		for line in self.lines:
			if len(string.strip(line)) and not self.commentre.match(line):
				sys.stderr.write("%s: rest %s\n" % (self.filename, line))

		# the targets allowed to be defined not-PHONY
		for target in ['install-exec', 'install-data', 'all', "uninstall"]:
			targ = self.target(target + '-hook')
			if targ:
				targ.is_phony = 1
			targ = self.target(target + '-local')
			if targ:
				targ.is_phony = 1
				
		for handler in handlerbase.handlers:
			handler.parse(self)
			
	def find_defines(self):
		
		current_cond = ""
		current_cond_true = 1
		index = 0
		while index < len(self.lines):
			line = self.lines[index]
			if self.commentre.match(line):
				index = index + 1
				continue
			define = definere.match(line)
			if define:
				varname = define.group(1)
				value = re.sub('#.*', '', define.group(3))
				if define.group(2) == '+':
					assert(not len(current_cond))
					if self.is_defined(varname):
						self.add_define(varname, value)
					else:
						print_error("%s: %s += used before assigned value to the variable\n" % (self.filename, varname))
				else:
					warn = self.is_defined(varname) or subst_vars.has_key(varname)

					# datadir got a second chance but will be warned about 
					if warn and varname in self.handled_overwrites and not varname == 'datadir':
						warn = 0
					if warn and len(current_cond) and not current_cond_true:
						warn = 0

					if warn:
						sys.stderr.write("%s: Warning: %s redefined\n"
										 % (self.filename, varname))

					self.add_define(varname, value, current_cond, current_cond_true)
						
				self.lines[index:index+1] = []
			elif line.startswith('if '):
				if len(current_cond):
					print_error('%s: nested automake conditionals '
								'(%s vs. %s)\n' % (self.filename,
												   current_cond,
												   string.strip(line[3:])))
					return
				current_cond = string.strip(line[3:])
				current_cond_true = 1
				self.lines[index:index+1] = []
			elif line.startswith('else'):
				current_cond_true = 0
				self.lines[index:index+1] = []
			elif line.startswith('endif'):
				current_cond = ""
				self.lines[index:index+1] = []
			else:
				index = index + 1

	def find_targets(self):
		targetre = re.compile(' *([^:]*)\s*:\s*(.*)')

		index = 0
		while index < len(self.lines):
			line = self.lines[index]
			if self.commentre.match(line):
				index = index + 1
				continue
			# it's a croax - defines can contain : chars too
			if definere.match(line):
				index = index + 1
				continue
			targmatch = targetre.match(line)
			if targmatch:
				targets = string.split(targmatch.group(1))
				deps = re.sub('#.*', '',  targmatch.group(2))
				deps = re.sub('\001', '', deps)
				newindex = index + 1
				while newindex < len(self.lines):
					if self.lines[newindex][0] == '\t':
						newindex = newindex + 1
						continue
					# white space only lines count as comments too
					if not len(string.strip(self.lines[newindex])) or self.commentre.match(self.lines[newindex]):
						newindex = newindex + 1
						continue
					break
				try:
					for target in targets:
						self.insertTarget(target, deps, self.lines[index+1:newindex], 1)
				except:
					sys.stderr.write("%s: target %s has an error\n" % (self.filename, target))
				self.lines[index:newindex] = []
			else:
				index = index + 1
		target = self.target('.PHONY')
		if target:
			target.is_phony = 1
			for targ in target.deps:
				otarg = self.target(targ)
				if not otarg:
					print_error("%s: target '%s' marked PHONY but isn't present\n" % (self.filename,
																					targ))
				else:
					otarg.is_phony = 1

	# does some basic checking for things that often break
	def check(self):
		for define in self.defines():
			if define.endswith('_LDFLAGS') or define == 'LDFLAGS':
				list = self.definition_rec(define)
				for str in list:
					if str.endswith('.la') or str.endswith('.lo'):
						print_error('%s: LDFLAGS contains libtool\n'
									'\tfile %s. These belong in LIBADD\n'
									'\t(for libs) or LDADD (for programs)\n' %
									(self.filename, str))
						continue
					if str.startswith('-L .') or str.startswith('-L.'):
						print_error('%s: seen -L. in your LDFLAGS. You shouldn\'t\n'
									'use -L relative paths but use relative paths to\n'
									'.la files in LDADD/LIBADD\n' % (self.filename))
						continue
			if define.endswith('_LIBADD') or define.endswith('_LDADD'):
				list = self.definition_rec(define)
				for str in list:
					if str.endswith('.la') and not os.path.basename(str).startswith('lib'):
						print('%s: %s contains a module. This is not portable!\n'
							  '     You can only link against libraries.' % (self.filename, define))
						continue
						

	def replace_srcdir(self, list):
		res = []
		Ire = re.compile('^-I([^/\$].*)')
		index = 0
		while index < len(list):
			l = list[index]
			if l == '-I':
				print('%s: found single -I argument. This is not portable.' % self.filename)
				list[index+1] = l + list[index+1]
				del list[index]
				continue
			l = re.sub('^-I\$\(srcdir\)', '-I' + self.rulef.source[:-1], l)
			match = Ire.match(l)
			if match:
				# strip the latest / - it looks ugly, no other reason
				if match.group(1) == '.':
					l = '-I' + self.rulef.build[:-1]
				else:
					l = '-I' + self.rulef.build + match.group(1)
			else:
				match = variablesre.match(l)
				if match and self.conds.has_key(match.group(2)):
					var = match.group(2)
					pvar = '%s_%s' % (self.canon_subdir, var)
					if not self.rulef.conds.has_key(pvar):
						list1 = self.replace_srcdir(self.conds[var][1])
						list2 = self.replace_srcdir(self.conds[var][2])
					
						self.rulef.conds[pvar] = (self.conds[var][0], list1, list2)
						l = '$(%s)%s' % (pvar, match.group(3))
					else:
						l = '$(%s)%s' % (pvar, match.group(3))
						
			res.append(l)
			index = index + 1
		return res
	
	def handle(self):

		self.add_define(self.canon_subdir + '_srcdir', '$(srcdir)')
		self.add_define(self.canon_subdir + '_builddir', '.')
		subst_vars[self.canon_subdir + '_srcdir'] = ''
		subst_vars[self.canon_subdir + '_builddir'] = ''

		self.find_binaries()
		self.move_conditionals_out_of_primaries()
		
		for handler in handlerbase.handlers:
			handler.handle(self)

		for bin in self.binaries.values():
			list = self.value_list(bin.canon_name + '_COMPILE_FIRST')
			for imp in list:
				self.translate_target(imp)
			for imp in list:
				for obj in bin.objs:
					self.rulef.insertTarget(self.rulef.build + obj, self.replace_builddir([imp]))
			bin.add_final_target(list)

	# overwritten from Makefile to not affect the parent
	def set_def_printed(self, definition):
		self.printed_defs[definition] = 1

	def in_srcdir(self, file):
		return os.path.exists(os.path.join(self.dirname, file))
		
	def userdirs(self):
		try:
			return self.userdirs
		except AttributeError:
			self.userdirs = []
			for key in self.defines():
				if key.endswith('dir'):
					self.userdirs.append(key[:-3])
			return self.userdirs


	def dirprefixes(self):
		# These are the directory names, which can be written
		# as variable prefixes (e.g. xxx_SOURCES, with xxx being one of the
		# dirs)
		# it's a subset of automake's recognized directories
		list = ["bin", "sbin", "libexec", "data", "sysconf", "sharedstate",
				"localstate", "lib", "info", "include", "man",
				"pkglib", "pkginclude", "pkgdata"]
		list.extend( self.userdirs() )
		return list

	def primaries(self):
		return ["PROGRAMS", "LIBRARIES", "SCRIPTS", "DATA", "HEADERS", "MANS",
				"TEXINFOS", "LTLIBRARIES"]

	def instance_binary(self, entry, prefix, type):
		prog = program.Program(self, entry, prefix, type)
		self.binaries[prog.name] = prog
						  
	# This finds all xxx_{PROGRAMS,{LT}LIBRARIES} and their sources
	def find_binaries(self):
	
		progre = re.compile('(.*)_(PROGRAMS|(LT)?LIBRARIES)')
		
		for key in self.defines():
			match = progre.match(key)
			if not match:
				continue

			prefix = match.group(1)
			suffix = match.group(2)
			kind = match.group(3)

			type = program.program_type(suffix)

			for entry in self.definition_rec(key):
				match = variablere.match(entry)
				if not match:
					self.instance_binary(entry, prefix, type)
				else:
					var = match.group(1)
					if not self.conds.has_key(var):
						print_error('%s: variable %s is not automake conditional, but can\'t be expanded\n' %
									(self.filename, var))
						continue
					for l in self.conds[var][1]:
						self.instance_binary(l, prefix, type)
					for l in self.conds[var][2]:
						self.instance_binary(l, prefix, type)

		for handler in handlerbase.handlers:
			handler.shuffle_binaries(self)
			
		for prog in self.binaries.values():
			prog.handle_sources( self.definition_rec( prog.canon_name + '_SOURCES' ) )
			prog.add_targets()

	def find_opts(self):
		self.options = {}
		self.options["foreign"] = 0
		self.options["qtonly"] = 0
		self.options["noautodist"] = 0
		self.options["foreign-libtool"] = 0
		self.options["nofinal"] = 0
		self.options["doxygen"] = 0
		for option in self.value_list("KDE_OPTIONS"):
			self.options[option] = 1
	
	def get_opt(self, opt):
		try:
			return self.options[opt]
		except:
			raise 'unknown option'
			
	def print_out(self, force):

		self.printed_defs = {}
	
		output = []
		
		output.append("# Makefile.in generated by automake replacement unsermake\n")
		output.append("# Unfortunately the header has to contain automake to make\n")
		output.append("# the dependencies work.\n")
		output.append("##########################################################\n")
		output.append("\n")
		output.append("@SET_MAKE@\n")
		output.append("VPATH = @srcdir@\n")
		output.append("\n")
		self.printed_defs["VPATH"] = 1
		self.printed_defs["MAKE"] = 1
		
		if self.subdir == '.':
			builddir = '.'
		else:
			builddir = '..'
			slashes = string.count(self.subdir, '/')
			for h in range(slashes):
				builddir = builddir + '/..'
		output.append('subdir = %s\n' % self.subdir)
		output.append('srcdir = @srcdir@\n')
		output.append('top_builddir = %s\n' % builddir)
		output.append('top_distdir = %s\n' % builddir)
		output.append('INSTALL = @INSTALL@\n')
		output.append('distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)\n')
		output.append("\n")
		
		self.printed_defs["subdir"] = 1
		self.printed_defs["srcdir"] = 1
		self.printed_defs["top_builddir"] = 1
		self.printed_defs["distdir"] = 1
		self.printed_defs["top_distdir"] = 1
		self.printed_defs["INSTALL"] = 1
		
		output.append("@am__include@ @am__quote@$(top_builddir)/MakeVars@am__quote@\n")
		output.append("\n")

		if self.canon_subdir != "top":
			output.append("top_srcdir = @top_srcdir@\n")
		output.append(self.canon_subdir + "_srcdir = @srcdir@\n")
		if self.subdir == '.':
			output.append(self.canon_subdir + "_builddir = .\n")
		else:
			output.append(self.canon_subdir + "_builddir = $(top_builddir)/$(subdir)\n")
		self.printed_defs[self.canon_subdir + "_srcdir"] = 1
		self.printed_defs[self.canon_subdir + "_builddir"] = 1
		self.printed_defs["top_srcdir"] = 1
		output.append("\n")
		
		if self.is_defined("DEP_FILES"):
			output.append("DEPDIR = @DEPDIR@\n")
			self.printed_defs["DEPDIR"] = 1
			self.print_out_definition(output, "DEP_FILES")
			output.append("\n")

		self.print_out_target(output, "all")
		output.append("\n")
		
		outputfilename = re.sub('.am$', '.rules.in', self.filename)
		rules_lines = []
		self.rulef.print_out(rules_lines)
		utilities.write_if_changed(outputfilename, rules_lines, force)
		output.append("@am__include@ @am__quote@Makefile.rules@am__quote@\n")
		outputfilename = re.sub('.am$', '.calls.in', self.filename)
		rules_lines = []
		self.callf.print_out(rules_lines)
		utilities.write_if_changed(outputfilename, rules_lines, force)
		
		for var in subst_vars.keys() + self.environment_variables + self.rulef.defines():
			self.printed_defs[var] = 1

		keys = self.targets.keys()
		keys.sort()
		for key in keys:
			if not key == "all":
				self.print_out_target(output, key)

		output.append('\n')
		output.append('# the following defines are only there for reference\n')
		keys = self.defines()
		keys.sort()
		for definition in keys:
			self.print_out_definition(output, definition)
			#if not self.printed_defs.has_key(definition):
			#	print '%s = %s' % (definition, string.join(self.defs[definition]))
		utilities.write_if_changed(re.sub('.am$', '.in', self.filename), output, force)

	def translate_target(self, target):
		targ = self.target(target)
		rulef = self.rulef
		
		if not targ:
			targ = self.target('$(srcdir)/' + target)
			lfs = rulef.source + target
		else:
			lfs = rulef.build + targ.target
			
		if targ and targ.user_specified:
			self.to_handle_targets.append(targ)

			for dep in targ.deps:
				self.translate_target(dep)

			self.rulef.insertTarget(lfs, [])
			
	def replace_builddir(self, deps, leaveout_vars=1):
		rulef = self.rulef
		newdeps = deps
		deps = []
		for dep in newdeps:
			if dep.startswith('./'):
				dep = rulef.build + dep[2:]
			elif dep[0] == '/': # absolute paths are rather seldom
				pass
			elif dep.startswith('../'):
				dep = os.path.normpath('$(top_builddir)/' +
									   self.subdir + '/' + dep)
			elif dep.startswith('$(srcdir)'):
				if dep[9] == '/':
					dep = rulef.source + dep[10:]
				else:
					dep = rulef.source + dep[9:]
			elif dep.startswith('$(top_srcdir)'):
				pass
			elif dep[0] == '$':
				if re.match('^\$\(top_builddir\)', dep):
					deps.append(dep)
					continue
				match = variablesre.match(dep)
				if not match or len(match.group(1)):
					print_error('%s: "%s" appears to be a variable, but is none. Assertion hit!\n' % (self.filename, dep))
					continue
				var = match.group(2)
				pvar = '%s_%s' % (self.canon_subdir, var)
				if self.conds.has_key(var):
					if not self.rulef.conds.has_key(pvar):
						list1 = self.replace_builddir(self.conds[var][1], leaveout_vars)
						list2 = self.replace_builddir(self.conds[var][2], leaveout_vars)
					
						self.rulef.conds[pvar] = (self.conds[var][0], list1, list2)
						deps.append('$(%s)%s' % (pvar, match.group(3)))
					else:
						deps.append('$(%s)%s' % (pvar, match.group(3)))
						
					continue
				elif subst_vars.has_key(var) and len(subst_vars[var]):
					deps.extend(self.replace_builddir(string.split(subst_vars[var] + match.group(3)), leaveout_vars))
					continue
				elif leaveout_vars:
					continue
			elif dep[0] == '-':
				if leaveout_vars:
					continue
			else:
				dep = self.rulef.build + dep
			deps.append(dep)
		return deps
	
	def rewrite_list(self, list):
		files = []
		for file in list:
			self.translate_target(file)
			match = variablere.match(file)
			if match:
				self.rewrite_cond(match.group(1))
				files.append('$(%s_%s)' % (self.canon_subdir, match.group(1)))
			else:
				dir = self.rulef.source
				if self.rulef.target(file) or self.target(file):
					dir = self.rulef.build
				if self.rulef.target(self.rulef.build + file):
					dir = self.rulef.build
				files.append(dir + file)
		return files
	
	def rewrite_cond(self, var):
		if not self.conds.has_key(var):
			print self.filename, var
		assert(self.conds.has_key(var))
		tuple = self.conds[var]
		new_tuple = (tuple[0], self.rewrite_list(tuple[1]),
					 self.rewrite_list(tuple[2]))
		self.rulef.conds[self.canon_subdir + '_' + var] = new_tuple

	def move_conditionals_out_of_primaries(self):
		primaries = self.primaries()
		# TODO: merge the beginning with the beginning of the next func.
		primaryre = re.compile('(.*)_([^_]*)')
		conds_keys = self.conds.keys()
		for key in conds_keys:
			match = primaryre.match(key)
			if not match or not match.group(2) in primaries:
				continue
			self.conds[key + "_CONTENT"] = self.conds[key]
			self.add_define(key, "$(%s_CONTENT)" % key)
			del self.conds[key]

	def add_install_target(self, install_rules, dirprefix, file, primary):
		my_install_rules = []
		basename = os.path.basename(file)
		basenamenoext = basename
		if basenamenoext.rfind('.') != -1:
			basenamenoext = basenamenoext[:basenamenoext.rfind('.')]
		mansect = ""

		dirname = '$(DESTDIR)$(%sdir)' % dirprefix
		if primary == 'MANS':
			match = self.mansectre.match(file)
			if not match:
				print_error('%s is an illegal manpage filename.\n' % file)
			else:
				mansect = match.group(1)
				dirname += "/man" + mansect
				assert(mansect in self.mansections)

		for rule in install_rules:
			rule = string.replace(rule, '@file@', file)
			rule = string.replace(rule, '@basename@', basename)
			rule = string.replace(rule, '@basenamenoext@', basenamenoext)
			rule = string.replace(rule, '@mansect@', mansect)
			my_install_rules.append(rule)

		target = '$(DESTDIR)$(%sdir)/%s' % (dirprefix, basename)
		deps = [file, '$(UNSERMAKE_FORCE_INSTALL)']

		self.rulef.insertTarget(target, deps,
							['@test -d %s || $(mkinstalldirs) %s' % (dirname, dirname)]
							+ my_install_rules )
		return target
		
	def collect_primaries(self):
		primaries = self.primaries()
		primaryre = re.compile('(.*)_([^_]*)')
		for key in self.defines():
			match = primaryre.match(key)
			if not match or not match.group(2) in primaries:
				continue
			primary = match.group(2)
			if self.conds.has_key(key):
				print_error('%s: found primary %s in conditional.\n' % (self.filename, key))
				continue
			files = self.rewrite_list(self.definition_rec(key))

			self.rulef.add_define("%s_%s" % (self.canon_subdir, key), files)
			if match.group(1) == 'check':
				self.rulef.insertTarget("check", "$(%s_%s)" % (self.canon_subdir, key), phony=1)
			elif match.group(1) != 'EXTRA':
				self.rulef.insertTarget("all-am-%s" % (self.canon_subdir),
										"$(%s_%s)" % (self.canon_subdir, key),
										phony=1)
			if match.group(1) in ['EXTRA', 'noinst', 'check']:
				continue

			varname = '%sdir' % match.group(1);
			if (not subst_vars.has_key(varname)) or (varname in self.handled_overwrites):
				if not self.rulef.is_defined('%s_%sdir' % (self.canon_subdir, match.group(1))):
					if primary == 'MANS':
						self.rulef.add_define('%s_%sdir' % (self.canon_subdir, match.group(1)),
											  '$(mandir)/man' + match.group(1)[-1])
					else:
						self.rulef.add_define('%s_%sdir' % (self.canon_subdir, match.group(1)),
											  self.definition_rec('%sdir' % match.group(1)))
				dirprefix = '%s_%s' % (self.canon_subdir, match.group(1))
			else:
				dirprefix = match.group(1)

			install_kind = 'exec'
			
			if primary == 'LTLIBRARIES':
				install_rules = ['$(LIBTOOL) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) @file@ $(DESTDIR)$(%sdir)' % dirprefix]
				uninstall_rules = [ 'f="`echo $$p | sed -e \'s|^.*/||\'`"; \\',
									'echo " $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(%sdir)/$$f"; \\' % dirprefix,
									'$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(%sdir)/$$f; \\' % dirprefix]
			elif primary == 'LIBRARIES':
				install_rules = ['$(INSTALL_DATA) @file@ $(DESTDIR)$(%sdir)/@basename@' % dirprefix,
								 '$(RANLIB) $(DESTDIR)$(%sdir)/@basename@' % dirprefix]
				uninstall_rules = ['f="`echo $$p | sed -e \'s|^.*/||\'`"; \\',
								   'echo " rm -f $(DESTDIR)$(%sdir)/$$f"; \\' % dirprefix,
								   'rm -f $(DESTDIR)$(%sdir)/$$f; \\' % dirprefix]
			elif primary in ['DATA', 'HEADERS']:
				install_rules = ['$(INSTALL_DATA) @file@ $(DESTDIR)$(%sdir)/@basename@' % dirprefix]
				uninstall_rules = ['f="`echo $$p | sed -e \'s|^.*/||\'`"; \\',
								   'echo " rm -f $(DESTDIR)$(%sdir)/$$f"; \\' % dirprefix,
								   'rm -f $(DESTDIR)$(%sdir)/$$f; \\' % dirprefix]
				install_kind = 'data'
			elif primary == 'PROGRAMS':
				install_rules = ['@p1=`echo @file@ |sed \'s/$(EXEEXT)$$//\'`; \\',
								 'if test -f @file@ || test -f $$p1; then \\',
								 'f=`echo $$p1|sed \'$(transform);s|^.*/||;s/$$/$(EXEEXT)/\'`; \\',
								 'echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install '
								 '$(INSTALL_PROGRAM) @file@ $(DESTDIR)$(%sdir)/$$f"; \\' % dirprefix,
								 '$(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install '
								 '$(INSTALL_PROGRAM) @file@ $(DESTDIR)$(%sdir)/$$f; else :;\\' % dirprefix,
								 'fi']
				uninstall_rules = ['f=`echo $$p|sed \'s/$(EXEEXT)$$//;$(transform);s|^.*/||;s/$$/$(EXEEXT)/\'`; \\',
								   'echo " rm -f $(DESTDIR)$(%sdir)/$$f"; \\' % dirprefix,
								   'rm -f $(DESTDIR)$(%sdir)/$$f; \\' % dirprefix]
			elif primary == 'SCRIPTS':
				install_rules = ['f="`echo @file@ |sed \'$(transform)\'| sed \'s|^.*/||\'`" \\'
								 'echo " $(INSTALL_SCRIPT) @file@ $(DESTDIR)$(%sdir)/$$f"; \\' % dirprefix,
								 '$(INSTALL_SCRIPT) @file@ $(DESTDIR)$(%sdir)/$$f; \\' % dirprefix]
				uninstall_rules = ['f="`echo $$p|sed \'$(transform)\' | sed \'s|^.*/||\'`"; \\',
								   'echo " rm -f $(DESTDIR)$(%sdir)/$$f"; \\' % dirprefix,
								   'rm -f $(DESTDIR)$(%sdir)/$$f; \\' % dirprefix]
			elif primary == 'MANS':
				installdir = '$(DESTDIR)$(%sdir)' % dirprefix
				manfilename = ''
				if match.group(1) == 'man':
					installdir += '/man@mansect@'
					manfilename = '@basename@'
				else:
					assert(match.group(1)[-1] in self.mansections)
					manfilename = '@basenamenoext@.%s' % match.group(1)[-1]
				install_rules = ['$(INSTALL_DATA) @file@ %s/%s' % (installdir, manfilename)]

				uninstall_rules = []
				uninstalldir = '$(DESTDIR)$(%sdir)' % dirprefix
				if match.group(1) == "man":
					manfilename = '$$f'
					uninstall_rules.append('s="`echo $$p | sed -e \'s|^.*\\.\\([0-9a-z]\\)[a-z]*$$|\\1|\'`"; \\')
					uninstalldir += "/man$$s";
				else:
					manfilename = '"`echo $$f | sed -e \'s|[^\\.]*$$|%s|\'`"' % match.group(1)[-1]

				uninstall_rules += ['f="`echo $$p | sed -e \'s|^.*/||\'`"; \\',
								    'echo " rm -f %s/%s"; \\' % (uninstalldir, manfilename),
								    'rm -f %s/%s; \\' % (uninstalldir, manfilename)]
				install_kind = 'data'
			else: 
				print('%s: install for %s unimplemented\n' % (self.filename, primary))
				install_rules = []
				uninstall_rules = []

			for file in files:
				vmatch = variablere.match(file)
				if vmatch:
					(cond, list_true, list_false) = self.rulef.conds[vmatch.group(1)]
					varname = 'installed-%s%s-%s' % (dirprefix, primary, vmatch.group(1))
					new_list_true = []
					new_list_false = []
					for file in list_true:
						target = self.add_install_target(install_rules, dirprefix, file, primary)
						new_list_true.append(target)
					for file in list_false:
						target = self.add_install_target(install_rules, dirprefix, file, primary)
						new_list_false.append(target)
					self.rulef.conds[varname] = (cond, new_list_true, new_list_false)
					self.rulef.insertTarget('install-%s-%s%s' % (self.canon_subdir, dirprefix, primary),
											'$(%s)' % varname, phony=1)
				else:
					target = self.add_install_target(install_rules, dirprefix, file, primary)
					self.rulef.insertTarget('install-%s-%s%s' % (self.canon_subdir, dirprefix, primary),
											target, phony=1)

			if len(files):
				self.rulef.insertTarget('uninstall-%s-%s%s' %	(self.canon_subdir, dirprefix, primary), [],
										['@list=\'$(%s_%s)\'; for p in $$list; do \\' % (self.canon_subdir, key)]
										+ uninstall_rules +
										['done'], phony=1)
				self.rulef.insertTarget('install-%s-%s' % (install_kind, self.canon_subdir),
										'install-%s-%s%s' %	(self.canon_subdir, dirprefix, primary), phony=1)
				self.rulef.insertTarget('uninstall', 'uninstall-%s-%s%s' %
										(self.canon_subdir, dirprefix, primary), phony=1)
			else:
				print_error("%s: Empty file list for %s\n" % (self.filename, key))
			
		local_deps = []
		for targ in ["install-exec", "install-data"]:
			if self.rulef.is_target(targ +  '-%s' % self.canon_subdir) and self.is_target(targ + "-hook"):
				self.rulef.insertTarget(targ, targ +  '-%s' % self.canon_subdir, phony=1)
				self.rulef.insertTarget(targ +  '-%s' % self.canon_subdir, [],
								  "cd " + self.rulef.build + " && $(MAKE) " + targ + "-hook", phony=1)
				local_deps.append(targ + '-%s' % (self.canon_subdir))
			elif self.rulef.is_target(targ +  '-%s' % self.canon_subdir):
				self.rulef.insertTarget(targ, targ +  '-%s' % self.canon_subdir, phony=1)
				local_deps.append(targ + '-%s' % (self.canon_subdir))
			elif self.is_target(targ + "-hook"):
				print_error("%s: Hook for target %s installed without this target being used\n" % (self.filename, targ))
				return

		self.rulef.insertTarget('install-am-%s' % (self.canon_subdir), local_deps, phony=1)
		
		# adding the default install targets
		self.rulef.insertTarget('install', ["install-data", "install-exec"], phony=1)
		self.rulef.insertTarget('install-exec', '', phony=1)
		self.rulef.insertTarget('install-data', '', phony=1)
			
	def collect(self):
		
		# adding default targets
		self.insertTarget("compile", "", phony=1)
		self.insertTarget("clean", "", phony=1)

		if len(self.rulef.dep_files):
			self.add_define("DEP_FILES", self.rulef.dep_files)

		for handler in handlerbase.handlers:
			handler.collect(self)
		
		for targ in ['install-exec', 'install-data', 'all', "uninstall"]:
			if self.is_target("%s-local" % targ):
				if not self.subdir == '.':
					subdir = os.path.basename(self.subdir)
					self.rulef.insertTarget("%s-local-%s" % (targ, self.canon_subdir), [],
											"cd " + self.rulef.build + " && $(MAKE) %s-local" % targ, phony=1)
					self.rulef.insertTarget(targ + '-am-%s' % self.canon_subdir, "%s-local-%s" % (targ, self.canon_subdir), phony=1)
					self.rulef.insertTarget(targ, targ + '-am-%s' % self.canon_subdir, phony=1)
				else:
					self.insertTarget(targ + '-am-%s' % self.canon_subdir, targ + "-local", phony=1)
			
		self.collect_primaries()
		if self.is_defined("CLEANFILES"):
			self.rulef.insertTarget("clean-%s-CLEANFILES" % self.canon_subdir,
									[], "rm -f " + string.join(self.replace_builddir(self.definition_rec("CLEANFILES"))), phony=1)
			self.rulef.insertTarget("clean", "clean-%s-CLEANFILES" % self.canon_subdir, phony=1)
			
		if self.is_defined("DISTCLEANFILES"):
			self.rulef.insertTarget("clean-%s-DISTCLEANFILES" % self.canon_subdir,
									[], "rm -f " + string.join(self.replace_builddir(self.definition_rec("DISTCLEANFILES"))), phony=1)
			self.rulef.insertTarget("clean", "clean-%s-DISTCLEANFILES" % self.canon_subdir, phony=1)

		for targ in self.to_handle_targets:
			dir = self.rulef.build
			if not self.target(targ.target):
				dir = rulef.source
			
			deps = []
			for dep in targ.deps:
				if dep[0] == '$':
					deps.append(dep)
				elif len(os.path.dirname(dep)):
					deps.append(dep)
				else:
					if self.rulef.is_target(self.rulef.build + dep):
						deps.append(self.rulef.build + dep)
					else:
						deps.append(self.rulef.source + dep)

			lfs = dir + targ.target
			if targ.target.startswith('$(srcdir)'):
				lfs = self.rulef.source + targ.target[10:]

			if not len(targ._rules): # that's the easy case
				self.rulef.insertTarget(lfs, self.replace_builddir(deps, 0))
			else:
				subdir = os.path.basename(self.subdir)
				if targ.target.startswith('$(srcdir)'):
					self.callf.insertTarget(lfs,
								self.replace_builddir(deps, 0),
								"cd " + self.build
								+ " && $(MAKE) '" + self.callf.source +
								targ.target[10:] + "'")
				else:
					self.callf.insertTarget(lfs,
								self.replace_builddir(deps, 0),
								"cd " + self.build
								+ " && $(MAKE) " + targ.target)

		deps = []
		for file in ['Makefile.am'] + self.am_includes:
			deps.append(self.rulef.source + file)
		deps.append('$(top_srcdir)/MakeVars.in')
		rule = "cd $(top_srcdir) && UNSERMAKE=\"%s\" %s %s/Makefile" % (os.environ['UNSERMAKE'],
																		os.environ['UNSERMAKE'], self.subdir)
		self.rulef.insertTarget(self.rulef.source + "Makefile.in", deps, rule)
		self.rulef.insertTarget(self.rulef.source + "Makefile.rules.in",
								self.rulef.source + "Makefile.in")
		self.callf.insertTarget(self.rulef.source + "Makefile.calls.in", 
								self.rulef.source + "Makefile.in")
			
		if not self.subdir == '.':
			for target in self.targets.values():
				if target.user_specified and target.has_rules() and not target.is_phony:
					self.insertTarget('$(top_builddir)/%s/%s' %
									  (self.subdir, target.target),
									  target.target)
			
			# for subdirs we need to generate aliases for ../<subdir>/target
			targets = self.rulef.targets.values()
			prefixlen = len(self.rulef.build)
			for target in targets:
				if target.target[:prefixlen] == self.rulef.build and not target.is_phony:
					targ = target.target[prefixlen:]
					# don't add rules the other way around than the above
					rhs = '$(top_builddir)/%s/%s' % (self.subdir, targ)
					if not self.is_target(rhs):
						# note, that we insert an empty command (the " ;" at the end
						# of the prerequisites), to avoid invoking any default commands
						self.insertTarget(targ, [rhs, ";"])
					elif not self.target(rhs).has_rules():
						self.insertTarget(targ, ";")

			self.insertTarget('Makefile', '$(top_builddir)/%s/Makefile' % self.subdir)
		else:
			deps = []
			deps.append('$(top_srcdir)/configure.in')
			deps.append('$(top_srcdir)/aclocal.m4')
			rule = "cd $(top_srcdir) && UNSERMAKE=\"%s\" %s" % (os.environ['UNSERMAKE'],
																os.environ['UNSERMAKE'])
			self.rulef.insertTarget(self.rulef.source + "MakeVars.in", deps, rule)
	
	def create_Makefile_rules(self):
		# this function is a bit tricky. In theory every Makefile* file is an entity of
		# it's own, but as all Makefile*.in files are updated at once from unsermake
		# it's prefered that they are updated at the same time - especially when doing
		# parallel make
		#
		# the other reason is that we need an uptodate Makefile even in subdirs it's
		# not used in as config.status will check for DEP_FILES and create dummy files
		# in it - which would otherwise break incremental make calls
		config_files = ""
		in_files = []
		makefiles = ["Makefile.rules", "Makefile.calls", "Makefile"]
		for file in makefiles:
			config_files += "%s/%s " % (self.rulef.subdir, file)
			in_files.append(self.source + file + ".in")
		config_files = string.strip(config_files)
		prefix = self.rulef.build
		if self.rulef.subdir == '.':
			prefix = ""
		self.rulef.insertTarget(prefix + 'Makefile.rules',
								['$(top_builddir)/config.status'] + in_files,
								["cd $(top_builddir) && " +
								 "CONFIG_FILES=\"" + config_files + "\" " + 
								 "CONFIG_HEADERS= "
								 "CONFIG_LINKS= $(SHELL) ./config.status"])
		self.callf.insertTarget(prefix + "Makefile.calls",
								prefix + "Makefile.rules")
		self.insertTarget(prefix + "Makefile",
						  prefix + "Makefile.rules")
		for file in makefiles:
			self.rulef.insertTarget("all-am-%s" % (self.canon_subdir),
									self.rulef.build + file,
									phony=1)
	
	def final_reorder(self):
		MakeFile.final_reorder(self)
		self.rulef.final_reorder()
		self.callf.final_reorder()

import sys, getopt, os

def main():
	top_makefile = None
	auxdir = "."
	
	global thisProg, verbose
	thisProg = os.path.basename(sys.argv[0])

	if not os.environ.has_key('UNSERMAKE'):
		os.environ['UNSERMAKE'] = os.path.abspath(sys.argv[0])
		
	optlist, given_files = getopt.getopt(sys.argv[1:], 'vhr:', [
		'gnits', 'add-missing', 'version', 'verbose', 'help', 'random='])

	# default value
	random_targets = 0
	
	for option, param in optlist:
		if option == '--version':
			print thisProg + " 0.3"
			print 'Written by Stephan Kulow using concepts of Michael Matz'
			print 'and Simon Hausmann. In parts based on concepts of "am_edit"'
			print 'and "GNU Automake".'
			print ''
			print 'This is free software, for now public domain, but I\'m'
			print 'planing to release it as GPL.'

			sys.exit(0)
		if option == '--verbose' or option == '-v':
			verbose = 1
		if option == '--help' or option == '-h':
			print "Usage: " + thisProg + " [OPTION] ... [dir]..."
			sys.exit(0)
		if option == '--random' or option == '-r':
			utilities.default_force = 0
			random_targets = string.atoi(param)

	if not os.path.exists("configure.in"):
		print 'There must be a configure.in in the current directory.'
		sys.exit(1)

	utilities._topsrcdir = os.path.abspath(os.curdir)

	sourcedir = os.path.abspath(os.path.dirname(sys.argv[0]))
	for file in os.listdir(sourcedir):
		if file.endswith('.um'):
			execfile(sourcedir + "/" + file)

	given_dirs = []
	for index in range(len(given_files)):
		filename = given_files[index]
		if not os.path.exists(filename + '.am'):
			sys.stderr.write('%s.am does not exist!\n' % filename)
			sys.exit(1)
		filename = os.path.normcase(os.path.abspath(filename))
		filename = filename[ len(utilities._topsrcdir) + 1: ]
		given_files[index] = filename
		filename = os.path.dirname(filename)
		if not len(filename):
			filename = '.'
		given_dirs.append(filename)

	# the remaining files, not beeing automake files
	# these need to be remade with config.status
	config_files = {}
	config_headers = {}

	makefiles = []
	global subst_vars
	subst_vars, files, headers, auxdir = utilities.parse_autoconf()

	for file in given_files:
		if not file in files:
			files.append(file)

	for file in files:
		dir = os.path.dirname(file)
		if not len(dir):
			dir = '.'

		if len(given_dirs) and not dir in given_dirs:
			continue
		# for every rules file there has to be a Makefile too
		if (file.endswith('.rules') or file.endswith('.calls')) and os.path.exists( file[:-6] + '.am'):
			pass
		elif os.path.exists( file + '.am'):
			makefiles.append( file + '.am' )
		elif os.path.exists( file + '.in') or file == 'MakeVars':
			file = os.path.basename( file )
			if config_files.has_key(dir):
				config_files[dir].append( file )
			else:
				config_files[dir] = [ file ]
		else:
			print_error('%s appears in configure files, but has no .in file\n' % file)

	for file in headers:
		dir = os.path.dirname(file)
		if not len(dir):
			dir = '.'

		if len(given_dirs) and not dir in given_dirs:
			continue
		file = os.path.basename( file )
		if config_headers.has_key(dir):
			config_headers[dir].append( file )
		else:
			config_headers[dir] = [ file ]
		
	# the backslash is very bad to have as end of line ;/
	if subst_vars.has_key("AMDEPBACKSLASH"):
		del subst_vars["AMDEPBACKSLASH"]
	lines = []
	keys = subst_vars.keys()
	keys.sort()
	for var in keys:
		lines.append('%s = @%s@\n' % (var, var))
	
	lines.append('INSTALL_HEADER = $(INSTALL_DATA)\n')
	lines.append("CXXLD = $(CXX)\n")
	lines.append("CLD = $(CC)\n")
	lines.append("depcomp = $(SHELL) %s/depcomp\n" % auxdir)
	lines.append("mkinstalldirs = $(SHELL) %s/mkinstalldirs\n" % auxdir)
	lines.append("AR = ar\n")
	lines.append("transform = @program_transform_name@\n")
	lines.append('UNSERMAKE_FORCE_INSTALL = \n')
	lines.append('VERBOSE := \n')
	lines.append('V_ECHO := test -n "$(VERBOSE)" || echo\n')
	lines.append('V_EXEC := \\\n' +
	             "	if test -n \"$(VERBOSE)\"; then \\\n" +
	             "	  echo \"$$@\"; \"$$@\"; \\\n" +
	             "	else \\\n" +
	             "	  rslt=$$(\"$$@\" 2>&1); stat=$$?; \\\n" +
	             "	  if test $$stat -ne 0; then \\\n" +
	             "	    echo \"$$@\"; echo \"$$rslt\" >&2; \\\n" +
	             "	  else \\\n" +
	             "	    test -n \"$$rslt\" && echo \"$$rslt\" >&2; \\\n" +
	             "	  fi; \\\n" +
	             "	  exit $$stat; \\\n" +
	             "	fi\n")
	lines.append('V_COMPILE = \\\n' +
	             "	if test -n \"$(VERBOSE)\"; then echo \"$$@\"; \"$$@\"; else rslt=$$(\"$$@\" 2>&1); fi; stat=$$?; \\\n" +
	             "	if test $$stat -ne 0; then \\\n" +
	             "	  if test -z \"$(VERBOSE)\"; then echo \"$$@\"; echo \"$$rslt\" >&2; fi; \\\n" +
	             "	else \\\n" +
	             "	  test -n \"$$rslt\" && echo \"$$rslt\" >&2; \\\n" +
	             "	  rm -f \"$$depfile\"; echo \"$$targetfile : \\\\\" > \"$$depfile\"; \\\n" +
	             "	  deps=`sed -e 's,.*:,,' $$tmpdepfile | sed -e 's,\\\\\\\\,,g'`; \\\n" +
	             "	  for file in $$deps; do \\\n" +
	             "	    case $$file in \\\n" +
	             "	      /*) echo \"$$file \\\\\" >> $$depfile ;; \\\n" +
	             "	      *) echo '$$(top_builddir)/'\"$(subdir)/$$file \\\\\" >> $$depfile ;; \\\n" +
	             "	    esac;\\\n" +
	             "	  done;\\\n" +
	             "	  echo '' >> $$depfile;\\\n" +
	             "	  for file in $$deps; do \\\n" +
	             "	    case $$file in \\\n" +
	             "	      /*) echo \"$$file:\" >> $$depfile ;; \\\n" +
	             "	      *) echo '$$(top_builddir)/'\"$(subdir)/$$file:\" >> $$depfile ;; \\\n" +
	             "	    esac; \\\n" +
	             "	  done; \\\n" +
	             "	fi; \\\n" +
	             "	rm -f \"$$tmpdepfile\"; exit $$stat\n")

	if not given_dirs or '.' in given_dirs:
		utilities.write_if_changed('MakeVars.in', lines)

	# and now we fake a little to keep it consistent
	for var in ["top_srcdir", "top_builddir", "CXXLD", "CLD", "depcomp", "mkinstalldirs",
				"AR", "INSTALL", "srcdir", "UNSERMAKE_FORCE_INSTALL",
				"VERBOSE", "V_ECHO", "V_EXEC", "V_COMPILE", "ACLOCAL_AMFLAGS"]:
		subst_vars[var] = ""
	if subst_vars.has_key("DEPDIR"):
		del subst_vars["DEPDIR"]
	
	for index in range(len(makefiles)):
		if not makefiles[index][0] == '/':
			makefiles[index] = os.path.normcase(os.path.abspath(makefiles[index]))

	makefiles.sort()

	# the following is a several pass thing. First we have to parse
	# all, then we have to do overall checks and inserting of targets
	# and then we can print the makefiles out
	amfiles = []
	dirs = {}

	for file in makefiles:
		makefile = AMFile(file)
		if config_files.has_key(makefile.subdir):
			makefile.rulef.set_configure_files( config_files[ makefile.subdir] )
		makefile.create_Makefile_rules()
		if config_headers.has_key(makefile.subdir):
			makefile.rulef.set_configure_headers( config_headers[ makefile.subdir] )
			
		amfiles.append(makefile)
		if makefile.subdir == '.':
			top_makefile = makefile
		dirs[makefile.subdir] = makefile

	for makefile in amfiles:
		if makefile.subdir != '.':
			dir = os.path.dirname(makefile.subdir)
			if len(dir):
				if not dirs.has_key(dir):
					if not len(given_dirs):
						print_error('%s has no Makefile in the parent directory %s\n' % (makefile.filename, dir))
				else:
					makefile.parent = dirs[dir]
					makefile.rulef.parent = dirs[dir].rulef
			elif top_makefile:
				makefile.parent = top_makefile
				makefile.rulef.parent = top_makefile.rulef
				
		makefile.handle()

	bins = []
	for makefile in amfiles:
		makefile.check()
		makefile.collect()
		bins.extend(makefile.binaries.values())
		if makefile.subdir == '.':
			makefile.insertTarget('$(top_srcdir)/configure', ['$(top_srcdir)/configure.in',
															  '$(top_srcdir)/aclocal.m4'],
								  'cd $(top_srcdir) && $(AUTOCONF)')
			makefile.insertTarget('$(top_srcdir)/aclocal.m4', ['$(top_srcdir)/configure.in', '$(top_srcdir)/acinclude.m4'],
								  'cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)')
			makefile.insertTarget('$(top_builddir)/config.status', ['$(top_srcdir)/configure'],
								  '$(SHELL) ./config.status --recheck')


	# now it's a good time to get warnings about left over srcdir
	del subst_vars["srcdir"]

	import random
	random.seed()

	for r in xrange(0, random_targets):
		b = random.choice(bins)
		b.add_random()
		bins.remove(b)

	for makefile in amfiles:
		makefile.final_reorder()
		
	if utilities.sys_exit_code:
		sys.exit(utilities.sys_exit_code)
		
	for makefile in amfiles:
		if len(given_dirs):
			if makefile.subdir in given_dirs:
				makefile.print_out(1)
		else:
			makefile.print_out(0)
		
main()

# f = AMFile("konq.am")
sys.exit(utilities.sys_exit_code)

# vim: ts=4
