import types, string
import utilities

class PhonyConflict(Exception):
	pass

class Target:
	def __init__(self, target, deps, rules, user_specified, phony):
		self.target = target
		if type(deps) == types.StringType:
			self.deps = string.split(deps)
		else:
			assert(type(deps) == type([]))
			self.deps = deps

		if type(rules) == types.StringType:
			rules = [ rules ]
			
		self._rules = []
		for rule in rules:
			striped = string.strip(rule)
			if len(striped) and not striped[0] == '#':
				if  not rule[0] == '\t':
					if user_specified:
						raise 'rule %s doesn\'t start with <tab>' % target
					self._rules.append(string.rstrip(rule))
				else:
					self._rules.append(string.rstrip(rule[1:]))
		self.user_specified = user_specified
		self.is_phony = phony

	def __repr__(self):
		ret = self.target + ": " + string.join(self.deps)
		for rule in self._rules:
			ret += "\n\t" + rule
		return ret
	
	def has_rules(self):
		return len(self._rules) != 0
	
	def merge(self, targ):
		assert(self.target == targ.target)
		if not self.is_phony == targ.is_phony:
			raise PhonyConflict
			
		for dep in targ.deps:
			if not dep in self.deps:
				self.deps.append(dep)

		if self._rules == targ._rules:
			return
		elif len(self._rules) and len(targ._rules):
			print self._rules
			print targ._rules
			raise ("two targets named '%s' define rules!" % self.target)
		else:
			self.user_specified = self.user_specified and targ.user_specified
			self._rules.extend(targ._rules)

	def print_out(self, output):
		output.append('%s: %s\n' % (self.target, string.join(self.deps)))
		for rule in self._rules:
			if rule[0] == '\002':
				output.append('%s\n' % string.replace(rule[1:], '\001', '\\\n'))
			else:
				output.append('\t%s\n' % string.replace(rule, '\001', '\\\n'))
		if len(self._rules):
			output.append("\n")

	def _used_defines_str(self, str):
		match = utilities.variablesre.match(str)
		if not match:
			return []
		if not len(match.group(3)):
			return [match.group(2)]
		else:
			return [match.group(2)] + self._used_defines_str(match.group(3))
		
	def used_defines(self):
		res = []
		for rule in self.deps + self._rules:
			strings = string.split(rule)
			for str in strings:
				res.extend(self._used_defines_str(str))
		return res
