#!/usr/bin/env python
#
# Copyright (c) 2006 Movial Corp. Veli Mankinen (veli.mankinen@movial.fi)
#

import os, sys, re, commands, warnings
from stat import *

files = []
ARCH = ""

############################################################################

def init_find():
	global files
	cmd = 'find . -print'
	files = os.popen(cmd).readlines()


####################################################

def find_files(pattern, execbit=False):
	gcc=[]
	
	for file in files:
		pathname = file[:-1]
		
		if not os.path.isfile(pathname):
			continue
		
		if not re.search(pattern, pathname):
			continue

		mode = os.stat(pathname)[ST_MODE]
		if execbit and not S_IMODE(mode) & 1:
			continue
		
		gcc.append(pathname)
	
	return gcc


####################################################

def diff_info(name, info, keys):
	if not info:
		return False

	for other in info[1:]:
		for key in keys:
			if info[0][key] != other[key]:
				print("\n#")
				print("# ERROR: Found multiple '%s' with unmatching versions." % name)
				for entry in info:
					print("# : %s" % entry['path'])
					print("#")
	
				print
				return True
	return False


####################################################

def check_version_str(info, locations):
	if not info:
		return 0

	ver_str_parts = info[0]['ver_str'].split()
	
	location_error = 0
	for loc in locations.keys():
		if ver_str_parts[loc] != locations[loc]:
			location_error = 1
		
	if location_error:
		print "# ERROR: '%s' version string error." % info[0]['path']
		print "#        " + info[0]['ver_str']
		print "#"
	

####################################################
####################################################

def print_gcc_info(gcc):
	info = []
	arch = "unknown"
	working_objdump = ""
	
	for entry in gcc:
		gcc_ver = "0.0"
		ret, output = commands.getstatusoutput(entry + ' -v 2>&1')
		if ret != 0:
			continue
		lines = output.split("\n")
		if lines:
			gcc_ver = lines[len(lines) - 1].strip()
		
		alien_tc = "yes"
		ret, output = commands.getstatusoutput("ldd " + entry)
		if ret != 0:
			continue
		lines = output.split("\n")
		for line in lines:
			if re.search('scratchbox', line):
				alien_tc = 'no'
				break

		noncano_name = "not-found"
		ret, output = commands.getstatusoutput(entry + ' -dumpmachine')
		if ret != 0:
			continue
		lines = output.split("\n")
		if len(lines) > 0:
			noncano_name = lines[0].strip()

		warnings.filterwarnings("ignore", "tmpnam is", RuntimeWarning)
		outfile = os.tmpnam()
		ret, output = commands.getstatusoutput("echo 'main(){}' | "+ entry +" -xc - -c -o "+ outfile)
		if ret != 0:
			continue
		objdump = entry[:-3] + "objdump"
		ret, output = commands.getstatusoutput(objdump +" -f "+ outfile)
		if ret != 0:
			continue
		working_objdump=objdump
		lines = output.split("\n")
		for line in lines:
			match = re.search('architecture: (.*), flags', line)
			if match:
				arch = match.groups()[0]
				break

		info.append({'path': entry, 'ver_str': gcc_ver, 'alien_tc': alien_tc, 'noncano_name': noncano_name, 'arch': arch})
	
	diff_info('gcc', info, ('ver_str', 'alien_tc', 'noncano_name', 'arch'))
	check_version_str(info, {0: 'gcc', 1: 'version'})
	
	if not info:
		return arch, working_objdump
		
	ver_str_parts = info[0]['ver_str'].split()
	ver_parts = ver_str_parts[2].split(".")
	cc_ver = ver_parts[0] + "." + ver_parts[1]
	cc_gcc_ver = ver_parts[0] + "." + ver_parts[1] + "." + ver_parts[2]
	
	print "ALIEN_TC = " + info[0]['alien_tc']
	print
	print "CC_VER = " + cc_ver
	print "CC_GCCVER = " + cc_gcc_ver
	print "CC_FULLVER = %s:$(CC_GCCVER)"%ver_parts[0]
	if float(cc_ver) >=3.4:
		print "CC_DEBIAN_DIR = gcc-3.4-debian"
	else:
		print "CC_DEBIAN_DIR = gcc-%s-debian"%cc_ver
	print
	return arch, working_objdump

#####################################################


def print_ld_info(ld):
	info = []
	multiple_ld_match = 1
	
	for entry in ld:
		lines = os.popen(entry + ' -v').readlines()

		if len(lines) > 0:
			ld_ver_str = lines[0].strip()
			info.append({'path': entry, 'ver_str': ld_ver_str})

	diff_info('ld', info, ('ver_str', ))
	check_version_str(info, {0: 'GNU', 1: 'ld', 2: 'version'})

	if len(info) == 0:
		return -1

	print "BINUTILS_FULLVER = " + info[0]['ver_str'].split()[3] + "-0+sb1"
	print


#####################################################

def print_libc_info(libc):
	info = []
	multiple_libc_match = 1
	
	for entry in libc:
		tmp = re.search("lib/libc-\d+.\d+\.\d+\.so$", entry)
		version = ""
		if tmp:
			version = tmp.group().replace('lib/libc-', '').replace('.so', '')
		
		if version:
			info.append({'path':entry, 'version': version})
		
	diff_info('libc', info, ('version', ))
	
	if len(info) > 0:
		print "LIBC_VER = " + info[0]['version']
	
	
#####################################################

def find_bin_dirs(arch, objdump):
	cmd = 'for i in `find . -perm +1 -type f | grep -v "\.so"`; do F=`'+ objdump +' -f $i 2>/dev/null`; if [ "x`echo $F | grep "architecture: '+ arch +', flags"`" != "x" ] ; then echo $i | rev | cut -d "/" -f 2- | rev; fi; done | sort -u'
	sys.stdout.write("LIBC_FILES_BINS = ")
	for dir in os.popen(cmd).readlines():
		sys.stdout.write(dir.strip()[2:] + " ")
	
	print


#####################################################

def find_lib_dirs(arch, objdump):
	cmd = 'for i in `find . -name \*\.so`; do echo $i | grep -q /gconv/ && continue ;F=`'+ objdump +' -f $i 2>/dev/null`; if [ "x`echo $F | grep "architecture: '+ arch +', flags"`" != "x" ] ; then echo $i | rev | cut -d "/" -f 2- | rev; fi; done | sort -u'

	# cmd = 'for i in `find . -name \*\.so`; do F=`file $(realpath $i)`; if [ "x`echo $F | grep '+ arch +' | grep "shared object"`" != "x" ] ; then echo $i | rev | cut -d "/" -f 2- | rev; fi; done | sort -u'
	sys.stdout.write("LIBC_FILES_LIBS = ")
	for dir in os.popen(cmd).readlines():
		sys.stdout.write(dir.strip()[2:] + " ")

	print


#####################################################

def print_versionh_info(versionh):
	info = []
	multiple_versionh_match = 1
	for entry in versionh:
		version = "unknown"
		for line in open(entry):
			match = re.search("UTS_RELEASE \"(.*)\"", line)
			if match and version=='unknown':
				version = match.groups()[0]
				continue
				
			match = re.search("LIBC_HEADERS_VERSION \"(.*)\"", line)
			if match and version=='unknown':
				version = match.groups()[0]
		
		headers_dir = os.path.abspath(os.path.dirname(entry) + "/..").replace(os.path.abspath(os.getcwd()), '')[1:]
		linux_headers_subdirs=[]
		for hdir in ['linux','asm','asm-generic']:
			if os.path.exists(os.path.join(headers_dir,hdir)):
				linux_headers_subdirs.append(hdir)

		info.append({'path':entry, 'version': version, 'headers_dir': headers_dir,
			'kheaders_dirs':" ".join(linux_headers_subdirs)})
		
	diff_info('kernel version.h', info, ('version', ))
	
	if info:
		print "HEADERS_DIR = $(COMPILER_DIR)/" + info[0]['headers_dir']
		print "LINUX_HEADERS_SUBDIRS = " + info[0]['kheaders_dirs']
		print "LINUX_HEADERS_VER = " + info[0]['version']
		print
	else:
		print "#\n# ERROR: Could not find headers info!\n#"


#####################################################

def print_aux_info():
	print 'CHECKSUM_FILE\t= ../../$(CONFIG:.conf=.checksums)'

#####################################################		

def print_mkheaders_info(mkheaders):
	info = []
	multiple_mkheaders_match = 1

	for entry in mkheaders:
		canonical = ""
		noncanonical = ""
		
		for line in open(entry):
			if not canonical:
				if line.startswith('target='):
					canonical = line[len('target='):].strip()
					continue
					
			if not noncanonical:
				tmp = re.search("^target_(noncanonical|alias)=.*", line)
				if tmp:
					noncanonical = re.sub("^target_(noncanonical|alias)=", '', tmp.group())

		if canonical and noncanonical:
			info.append({'path': entry, 'canonical': canonical, 'noncanonical': noncanonical})

	diff_info('architecture', info, ('canonical', 'noncanonical'))
	if info:
		parts = info[0]['canonical'].split("-")
		if len(parts) != 4:
			print "#\n# ERROR: with canonical name: " + info[0]['canonical']
			return -1
		
		print "ARCH = " + parts[0]
		print "SUB_ARCH = $(ARCH)"
		print "VENDOR = " + parts[1] + "-"
		print "TOOLCHAIN_PREFIX_END = " + parts[3] + "-"
		print "TARGET_END = -" + parts[3] 
		print
	else:
		print "#\n# ERROR: Could not find machine info!\n#"


############################################################################

init_find()

comp_name = os.path.abspath(os.getcwd()).replace(os.path.abspath(os.getcwd() + "/.."), '')[1:]
print "COMPILER_NAME = " + comp_name
print "COMPILER_PACKAGE = <you have to fill in this one>"

gcc = find_files(".*cc$", True)
arch, objdump = print_gcc_info(gcc)

mkheaders = find_files(".*/mkheaders$", True)
print_mkheaders_info(mkheaders)

ld = find_files(".*ld$", True)
print_ld_info(ld)

versionh = find_files(".*linux/version.h$", False)
print_versionh_info(versionh)

libc = find_files(".*lib/libc-\d+.\d+\.\d+\.so$", False)
print_libc_info(libc)

if arch and objdump:
	find_bin_dirs(arch, objdump)
	find_lib_dirs(arch, objdump)
else:
	print "#\n# ERROR: I don't have arch and therefore cannot find bin and lib dirs."
print_aux_info()




