# Copyright 2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

import os as _os
import re

from portage import _unicode_decode
from portage.exception import InvalidData

#########################################################
#	This an re-implementaion of dev-util/lafilefixer-0.5.
#	rewrite_lafile() takes the contents of an lafile as a string
#	It then parses the dependency_libs and inherited_linker_flags
#	entries. 
#	We insist on dependency_libs being present. inherited_linker_flags
#	is optional.
#	There are strict rules about the syntax imposed by libtool's libltdl.
#	See 'parse_dotla_file' and 'trim' functions in libltdl/ltdl.c.
#	Note that duplicated entries of dependency_libs and inherited_linker_flags
#	are ignored by libtool (last one wins), but we treat it as error (like
#	lafilefixer does).
#	What it does:
#		* Replaces all .la files with absolut paths in dependency_libs with
#		  corresponding -l* and -L* entries 
#		  (/usr/lib64/libfoo.la -> -L/usr/lib64 -lfoo)
#		* Moves various flags (see flag_re below) to inherited_linker_flags,
#		  if such an entry was present.
#		* Reorders dependency_libs such that all -R* entries precede -L* entries
#		  and these precede all other entries.
#		* Remove duplicated entries from dependency_libs
#		* Takes care that no entry to inherited_linker_flags is added that is
#		  already there.
#########################################################

#These regexes are used to parse the interesting entries in the la file
dep_libs_re = re.compile(b"dependency_libs='(?P<value>[^']*)'$")
inh_link_flags_re = re.compile(b"inherited_linker_flags='(?P<value>[^']*)'$")

#regexes for replacing stuff in -L entries. 
#replace 'X11R6/lib' and 'local/lib' with 'lib', no idea what's this about.
X11_local_sub = re.compile(b"X11R6/lib|local/lib")
#get rid of the '..'
pkgconfig_sub1 = re.compile(b"usr/lib[^/]*/pkgconfig/\.\./\.\.")
pkgconfig_sub2 = re.compile(b"(?P<usrlib>usr/lib[^/]*)/pkgconfig/\.\.")

#detect flags that should go into inherited_linker_flags instead of dependency_libs
flag_re = re.compile(b"-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads")

def _parse_lafile_contents(contents):
	"""
	Parses 'dependency_libs' and 'inherited_linker_flags' lines.
	"""

	dep_libs = None
	inh_link_flags = None

	for line in contents.split(b"\n"):
		m = dep_libs_re.match(line)
		if m:
			if dep_libs is not None:
				raise InvalidData("duplicated dependency_libs entry")
			dep_libs = m.group("value")
			continue

		m = inh_link_flags_re.match(line)
		if m:
			if inh_link_flags is not None:
				raise InvalidData("duplicated inherited_linker_flags entry")
			inh_link_flags = m.group("value")
			continue

	return dep_libs, inh_link_flags

def rewrite_lafile(contents):
	"""
	Given the contents of an .la file, parse and fix it.
	This operates with strings of raw bytes (assumed to contain some ascii
	characters), in order to avoid any potential character encoding issues.
	Raises 'InvalidData' if the .la file is invalid.
	@param contents: the contents of a libtool archive file
	@type contents: bytes
	@rtype: tuple
	@returns: (True, fixed_contents) if something needed to be
		fixed, (False, None) otherwise.
	"""
	#Parse the 'dependency_libs' and 'inherited_linker_flags' lines.
	dep_libs, inh_link_flags = \
		_parse_lafile_contents(contents)

	if dep_libs is None:
		raise InvalidData("missing or invalid dependency_libs")

	new_dep_libs = []
	new_inh_link_flags = []
	librpath = []
	libladir = []

	if inh_link_flags is not None:
		new_inh_link_flags = inh_link_flags.split()

	#Check entries in 'dependency_libs'.
	for dep_libs_entry in dep_libs.split():
		if dep_libs_entry.startswith(b"-l"):
			#-lfoo, keep it
			if dep_libs_entry not in new_dep_libs:
				new_dep_libs.append(dep_libs_entry)

		elif dep_libs_entry.endswith(b".la"):
			#Two cases:
			#1) /usr/lib64/libfoo.la, turn it into -lfoo and append -L/usr/lib64 to libladir
			#2) libfoo.la, keep it
			dir, file = _os.path.split(dep_libs_entry)

			if not dir or not file.startswith(b"lib"):
				if dep_libs_entry not in new_dep_libs:
					new_dep_libs.append(dep_libs_entry)
			else:
				#/usr/lib64/libfoo.la -> -lfoo
				lib = b"-l" + file[3:-3]
				if lib not in new_dep_libs:
					new_dep_libs.append(lib)
				#/usr/lib64/libfoo.la -> -L/usr/lib64
				ladir = b"-L" + dir
				if ladir not in libladir:
					libladir.append(ladir)

		elif dep_libs_entry.startswith(b"-L"):
			#Do some replacement magic and store them in 'libladir'.
			#This allows us to place all -L entries at the beginning
			#of 'dependency_libs'.
			ladir = dep_libs_entry
			
			ladir = X11_local_sub.sub(b"lib", ladir)
			ladir = pkgconfig_sub1.sub(b"usr", ladir)
			ladir = pkgconfig_sub2.sub(b"\g<usrlib>", ladir)
			
			if ladir not in libladir:
				libladir.append(ladir)

		elif dep_libs_entry.startswith(b"-R"):
			if dep_libs_entry not in librpath:
				librpath.append(dep_libs_entry)

		elif flag_re.match(dep_libs_entry):
			#All this stuff goes into inh_link_flags, if the la file has such an entry.
			#If it doesn't, they stay in 'dependency_libs'.
			if inh_link_flags is not None:
				if dep_libs_entry not in new_inh_link_flags:
					new_inh_link_flags.append(dep_libs_entry)
			else:
				if dep_libs_entry not in new_dep_libs:
					new_dep_libs.append(dep_libs_entry)

		else:
			raise InvalidData("Error: Unexpected entry '%s' in 'dependency_libs'" \
				% _unicode_decode(dep_libs_entry))

	#What should 'dependency_libs' and 'inherited_linker_flags' look like?
	expected_dep_libs = b""
	for x in (librpath, libladir, new_dep_libs):
		if x:
			expected_dep_libs += b" " + b" ".join(x)

	expected_inh_link_flags = b""
	if new_inh_link_flags:
		expected_inh_link_flags += b" " + b" ".join(new_inh_link_flags)

	#Don't touch the file if we don't need to, otherwise put the expected values into
	#'contents' and write it into the la file.

	changed = False
	if dep_libs != expected_dep_libs:
		contents = contents.replace(b"dependency_libs='" + dep_libs + b"'", \
			b"dependency_libs='" + expected_dep_libs + b"'")
		changed = True

	if inh_link_flags is not None and expected_inh_link_flags != inh_link_flags:
		contents = contents.replace(b"inherited_linker_flags='" + inh_link_flags + b"'", \
			b"inherited_linker_flags='" + expected_inh_link_flags + b"'")
		changed = True

	if changed:
		return True, contents
	else:
		return False, None
