#! /usr/bin/env python
# encoding: utf-8
# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file

import sys
if sys.hexversion < 0x020400f0: from sets import Set as set
import os,re,sys,shutil
from waflib import Utils,Errors
exclude_regs='''
**/*~
**/#*#
**/.#*
**/%*%
**/._*
**/CVS
**/CVS/**
**/.cvsignore
**/SCCS
**/SCCS/**
**/vssver.scc
**/.svn
**/.svn/**
**/BitKeeper
**/.git
**/.git/**
**/.gitignore
**/.bzr
**/.bzrignore
**/.bzr/**
**/.hg
**/.hg/**
**/_MTN
**/_MTN/**
**/.arch-ids
**/{arch}
**/_darcs
**/_darcs/**
**/.DS_Store'''
def split_path(path):
	return path.split('/')
def split_path_cygwin(path):
	if path.startswith('//'):
		ret=path.split('/')[2:]
		ret[0]='/'+ret[0]
		return ret
	return path.split('/')
re_sp=re.compile('[/\\\\]')
def split_path_win32(path):
	if path.startswith('\\\\'):
		ret=re.split(re_sp,path)[2:]
		ret[0]='\\'+ret[0]
		return ret
	return re.split(re_sp,path)
if sys.platform=='cygwin':
	split_path=split_path_cygwin
elif Utils.is_win32:
	split_path=split_path_win32
class Node(object):
	__slots__=('name','sig','children','parent','cache_abspath','cache_isdir')
	def __init__(self,name,parent):
		self.name=name
		self.parent=parent
		if parent:
			if name in parent.children:
				raise Errors.WafError('node %s exists in the parent files %r already'%(name,parent))
			parent.children[name]=self
	def __setstate__(self,data):
		self.name=data[0]
		self.parent=data[1]
		if data[2]is not None:
			self.children=data[2]
		if data[3]is not None:
			self.sig=data[3]
	def __getstate__(self):
		return(self.name,self.parent,getattr(self,'children',None),getattr(self,'sig',None))
	def __str__(self):
		return self.name
	def __repr__(self):
		return self.abspath()
	def __hash__(self):
		return id(self)
	def __eq__(self,node):
		return id(self)==id(node)
	def __copy__(self):
		raise Errors.WafError('nodes are not supposed to be copied')
	def read(self,flags='r'):
		return Utils.readf(self.abspath(),flags)
	def write(self,data,flags='w'):
		f=None
		try:
			f=open(self.abspath(),flags)
			f.write(data)
		finally:
			if f:
				f.close()
	def chmod(self,val):
		os.chmod(self.abspath(),val)
	def delete(self):
		try:
			if getattr(self,'children',None):
				shutil.rmtree(self.abspath())
			else:
				os.unlink(self.abspath())
		except:
			pass
		try:
			delattr(self,'children')
		except:
			pass
	def suffix(self):
		k=max(0,self.name.rfind('.'))
		return self.name[k:]
	def height(self):
		d=self
		val=-1
		while d:
			d=d.parent
			val+=1
		return val
	def listdir(self):
		lst=Utils.listdir(self.abspath())
		lst.sort()
		return lst
	def mkdir(self):
		if getattr(self,'cache_isdir',None):
			return
		try:
			self.parent.mkdir()
		except:
			pass
		if self.name:
			try:
				os.makedirs(self.abspath())
			except OSError:
				pass
			if not os.path.isdir(self.abspath()):
				raise Errors.WafError('Could not create the directory %s'%self.abspath())
			try:
				self.children
			except:
				self.children={}
		self.cache_isdir=True
	def find_node(self,lst):
		if isinstance(lst,str):
			lst=[x for x in split_path(lst)if x and x!='.']
		cur=self
		for x in lst:
			if x=='..':
				cur=cur.parent or cur
				continue
			try:
				if x in cur.children:
					cur=cur.children[x]
					continue
			except:
				cur.children={}
			cur=self.__class__(x,cur)
			try:
				os.stat(cur.abspath())
			except:
				del cur.parent.children[x]
				return None
		ret=cur
		try:
			os.stat(ret.abspath())
		except:
			del ret.parent.children[ret.name]
			return None
		try:
			while not getattr(cur.parent,'cache_isdir',None):
				cur=cur.parent
				cur.cache_isdir=True
		except AttributeError:
			pass
		return ret
	def make_node(self,lst):
		if isinstance(lst,str):
			lst=[x for x in split_path(lst)if x and x!='.']
		cur=self
		for x in lst:
			if x=='..':
				cur=cur.parent or cur
				continue
			if getattr(cur,'children',{}):
				if x in cur.children:
					cur=cur.children[x]
					continue
			else:
				cur.children={}
			cur=self.__class__(x,cur)
		return cur
	def search(self,lst):
		if isinstance(lst,str):
			lst=[x for x in split_path(lst)if x and x!='.']
		cur=self
		try:
			for x in lst:
				if x=='..':
					cur=cur.parent or cur
				else:
					cur=cur.children[x]
			return cur
		except:
			pass
	def path_from(self,node):
		c1=self
		c2=node
		c1h=c1.height()
		c2h=c2.height()
		lst=[]
		up=0
		while c1h>c2h:
			lst.append(c1.name)
			c1=c1.parent
			c1h-=1
		while c2h>c1h:
			up+=1
			c2=c2.parent
			c2h-=1
		while id(c1)!=id(c2):
			lst.append(c1.name)
			up+=1
			c1=c1.parent
			c2=c2.parent
		for i in range(up):
			lst.append('..')
		lst.reverse()
		return os.sep.join(lst)or'.'
	def abspath(self):
		try:
			return self.cache_abspath
		except:
			pass
		if os.sep=='/':
			if not self.parent:
				val=os.sep
			elif not self.parent.name:
				val=os.sep+self.name
			else:
				val=self.parent.abspath()+os.sep+self.name
		else:
			if not self.parent:
				val=''
			elif not self.parent.name:
				val=self.name+os.sep
			else:
				val=self.parent.abspath().rstrip(os.sep)+os.sep+self.name
		self.cache_abspath=val
		return val
	def is_child_of(self,node):
		p=self
		diff=self.height()-node.height()
		while diff>0:
			diff-=1
			p=p.parent
		return id(p)==id(node)
	def ant_iter(self,accept=None,maxdepth=25,pats=[],dir=False,src=True,remove=True):
		dircont=self.listdir()
		dircont.sort()
		try:
			lst=set(self.children.keys())
			if remove:
				for x in lst-set(dircont):
					del self.children[x]
		except:
			self.children={}
		for name in dircont:
			npats=accept(name,pats)
			if npats and npats[0]:
				accepted=[]in npats[0]
				node=self.make_node([name])
				isdir=os.path.isdir(node.abspath())
				if accepted:
					if isdir:
						if dir:
							yield node
					else:
						if src:
							yield node
				if getattr(node,'cache_isdir',None)or isdir:
					node.cache_isdir=True
					if maxdepth:
						for k in node.ant_iter(accept=accept,maxdepth=maxdepth-1,pats=npats,dir=dir,src=src,remove=remove):
							yield k
		raise StopIteration
	def ant_glob(self,*k,**kw):
		src=kw.get('src',True)
		dir=kw.get('dir',False)
		excl=kw.get('excl',exclude_regs)
		incl=k and k[0]or kw.get('incl','**')
		def to_pat(s):
			lst=Utils.to_list(s)
			ret=[]
			for x in lst:
				x=x.replace('\\','/').replace('//','/')
				if x.endswith('/'):
					x+='**'
				lst2=x.split('/')
				accu=[]
				for k in lst2:
					if k=='**':
						accu.append(k)
					else:
						k=k.replace('.','[.]').replace('*','.*').replace('?','.').replace('+','\\+')
						k='^%s$'%k
						try:
							accu.append(re.compile(k))
						except Exception ,e:
							raise Errors.WafError("Invalid pattern: %s"%k,e)
				ret.append(accu)
			return ret
		def filtre(name,nn):
			ret=[]
			for lst in nn:
				if not lst:
					pass
				elif lst[0]=='**':
					ret.append(lst)
					if len(lst)>1:
						if lst[1].match(name):
							ret.append(lst[2:])
					else:
						ret.append([])
				elif lst[0].match(name):
					ret.append(lst[1:])
			return ret
		def accept(name,pats):
			nacc=filtre(name,pats[0])
			nrej=filtre(name,pats[1])
			if[]in nrej:
				nacc=[]
			return[nacc,nrej]
		ret=[x for x in self.ant_iter(accept=accept,pats=[to_pat(incl),to_pat(excl)],maxdepth=25,dir=dir,src=src,remove=kw.get('remove',True))]
		if kw.get('flat',False):
			return' '.join([x.path_from(self)for x in ret])
		return ret
	def find_nodes(self,find_dirs=True,find_files=True,match_fun=lambda x:True):
		x="""
		Recursively finds nodes::

			def configure(cnf):
				cnf.find_nodes()

		:param find_dirs: whether to return directories
		:param find_files: whether to return files
		:param match_fun: matching function, taking a node as parameter
		:rtype generator
		:return: a generator that iterates over all the requested files
		"""
		files=self.listdir()
		for f in files:
			node=self.make_node([f])
			if os.path.isdir(node.abspath()):
				if find_dirs and match_fun(node):
					yield node
				gen=node.find_nodes(find_dirs,find_files,match_fun)
				for g in gen:
					yield g
			else:
				if find_files and match_fun(node):
					yield node
	def is_src(self):
		cur=self
		x=id(self.ctx.srcnode)
		y=id(self.ctx.bldnode)
		while cur.parent:
			if id(cur)==y:
				return False
			if id(cur)==x:
				return True
			cur=cur.parent
		return False
	def is_bld(self):
		cur=self
		y=id(self.ctx.bldnode)
		while cur.parent:
			if id(cur)==y:
				return True
			cur=cur.parent
		return False
	def get_src(self):
		cur=self
		x=id(self.ctx.srcnode)
		y=id(self.ctx.bldnode)
		lst=[]
		while cur.parent:
			if id(cur)==y:
				lst.reverse()
				return self.ctx.srcnode.make_node(lst)
			if id(cur)==x:
				return self
			lst.append(cur.name)
			cur=cur.parent
		return self
	def get_bld(self):
		cur=self
		x=id(self.ctx.srcnode)
		y=id(self.ctx.bldnode)
		lst=[]
		while cur.parent:
			if id(cur)==y:
				return self
			if id(cur)==x:
				lst.reverse()
				return self.ctx.bldnode.make_node(lst)
			lst.append(cur.name)
			cur=cur.parent
		lst.reverse()
		if lst and Utils.is_win32 and len(lst[0])==2 and lst[0].endswith(':'):
			lst[0]=lst[0][0]
		return self.ctx.bldnode.make_node(['__root__']+lst)
	def find_resource(self,lst):
		if isinstance(lst,str):
			lst=[x for x in split_path(lst)if x and x!='.']
		node=self.get_bld().search(lst)
		if not node:
			self=self.get_src()
			node=self.find_node(lst)
		try:
			pat=node.abspath()
			if os.path.isdir(pat):
				return None
		except:
			pass
		return node
	def find_or_declare(self,lst):
		if isinstance(lst,str):
			lst=[x for x in split_path(lst)if x and x!='.']
		node=self.get_bld().search(lst)
		if node:
			if not os.path.isfile(node.abspath()):
				node.sig=None
				try:
					node.parent.mkdir()
				except:
					pass
			return node
		self=self.get_src()
		node=self.find_node(lst)
		if node:
			if not os.path.isfile(node.abspath()):
				node.sig=None
				try:
					node.parent.mkdir()
				except:
					pass
			return node
		node=self.get_bld().make_node(lst)
		node.parent.mkdir()
		return node
	def find_dir(self,lst):
		if isinstance(lst,str):
			lst=[x for x in split_path(lst)if x and x!='.']
		node=self.find_node(lst)
		try:
			if not os.path.isdir(node.abspath()):
				return None
		except(OSError,AttributeError):
			return None
		return node
	def change_ext(self,ext,ext_in=None):
		name=self.name
		if ext_in is None:
			k=name.rfind('.')
			if k>=0:
				name=name[:k]+ext
			else:
				name=name+ext
		else:
			name=name[:-len(ext_in)]+ext
		return self.parent.find_or_declare([name])
	def nice_path(self,env=None):
		return self.path_from(self.ctx.launch_node())
	def bldpath(self):
		return self.path_from(self.ctx.bldnode)
	def srcpath(self):
		return self.path_from(self.ctx.srcnode)
	def relpath(self):
		cur=self
		x=id(self.ctx.bldnode)
		while cur.parent:
			if id(cur)==x:
				return self.bldpath()
			cur=cur.parent
		return self.srcpath()
	def bld_dir(self):
		return self.parent.bldpath()
	def bld_base(self):
		s=os.path.splitext(self.name)[0]
		return self.bld_dir()+os.sep+s
	def get_bld_sig(self):
		try:
			ret=self.ctx.hash_cache[id(self)]
		except KeyError:
			pass
		except AttributeError:
			self.ctx.hash_cache={}
		else:
			return ret
		if not self.is_bld()or self.ctx.bldnode is self.ctx.srcnode:
			self.sig=Utils.h_file(self.abspath())
		self.ctx.hash_cache[id(self)]=ret=self.sig
		return ret
pickle_lock=Utils.threading.Lock()
class Nod3(Node):
	pass
