#!/usr/bin/tclsh

# 
# SRT - Secure, Reliable, Transport
# Copyright (c) 2017 Haivision Systems Inc.
# 
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# 
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
# 
# You should have received a copy of the GNU Lesser General Public
# License along with this library; If not, see <http://www.gnu.org/licenses/>
# 

# This is a general-purpose configure script, which is a user-friendly
# wrapper to call the cmake. Note that --help shows you only the options
# that are explicitly defined, but which exactly options are really
# supported, depends on what is defined in CMakeLists.txt. Just every
# case of --long-option is changed into LONG_OPTION cmake variable.
# However some of options MENTIONED IN THE HELP TEXT may be handled
# by the configure script before passing to cmake (and maybe turned
# into something else).
#
# The build-specific option processing is done in configure-data.tcl file.
#
# The idea is that CMakeLists.txt contains things that are highly
# customizable, but no system or option autodetection AWA "sensible
# defaults" are provided. This is done by this script.


set here [file dirname $argv0]

set options ""
set toolchain_changers ""

source $here/configure-data.tcl

# Update alias with default alias
dict set alias --prefix --cmake-install-prefix=

proc resolve opt {
	set type arg
	set pos [string first $opt =]
	if { $pos == -1 } {
		set type bool
		set mark ""
	} else {
		set type arg
		set mark [string range $opt $pos+1 end]
		set opt [string range $opt 0 $pos-1]
	}
	set var [string toupper [string map {- _ + x} $opt]]
	return [list --$opt $var $type $mark]
}

foreach {o desc} $options {
	lassign [resolve $o] optname optvar opttype optmark
	set opt($optname) [list $optvar $opttype $optmark]
	set info($optname) $desc
}


if { $argv == "--help" } {
	puts stderr "Usage: ./configure \[options\]"
	puts stderr "OPTIONS:"
	foreach o [lsort [array names opt]] {
		lassign $opt($o) unu type mark
		set imark ""
		if { $mark != "" } {
			set imark "=$mark"
		}
		puts stderr "\t$o$imark - $info($o)"
	}
	
	exit 1
}

if { [info proc init] != "" } {
	init
}

#parray opt

set saveopt ""
set optkeys ""

set dryrun 0
set type ""

foreach a $argv {
	if { [info exists val] } { unset val }

	if { $saveopt != "" } {
		set optval($saveopt) $a
		set saveopt ""
		continue
	}

	if { [string range $a 0 1] != "--" } {
		error "Unexpected argument '$a'. Options must start with --"
	}

	if { $a == "--dryrun" } {
		set dryrun 1
		continue
	}

	set type ""

	if { [string first = $a] != -1 } {
		lassign [split $a =] a val
	}

	if { [dict exists $::alias $a] } {
		set aname [dict get $::alias $a]
		if { [string first = $aname] != -1 } {
			lassign [split $aname =] a aval
			set type arg
		}
	}

	if { ![info exists opt($a)] } {
		#puts stderr "WARNING: Unknown option: $a"
		# But still, simply turn the option to assign-based use.
		lassign [resolve [string range $a 2 end]] oname var
		if { ![info exists val] && $type == "" } {
			set type bool
		}
	} else {
		lassign $opt($a) var type
	}

	if { $type == "bool" } {
		if { ![info exists val] } {
			set val 1
		}
		set optval($a) $val
	} elseif { [info exists val] } {
		set optval($a) $val
	} else {
		set saveopt $a
	}

	lappend optkeys $a
}

if { $saveopt != "" } {
	error "Extra unhandled argument: $saveopt"
}

set cmakeopt ""

if { [info proc preprocess] != "" } {
	preprocess
}

# Check if there were new values added not added to optkeys
foreach a [array names optval] {
	if { $a ni $optkeys } {
		lappend optkeys $a
	}
}


foreach a $optkeys {

	if { ![info exists optval($a)] } {
		continue  ;# user action might have removed it.
	}

	if { ![info exists opt($a)] } {
		#puts stderr "WARNING: Unknown option: $a"
		# But still, simply turn the option to assign-based use.
		lassign [resolve [string range $a 2 end]] oname var
		if { ![info exists val] && $type == "" } {
			set type bool
		}
	} else {
		lassign $opt($a) var type
	}

	set val $optval($a)
	lappend cmakeopt "-D$var=$val"
}


if { [info proc postprocess] != "" } {
	postprocess
}

#puts "VARSPEC: $cmakeopt"

set cmd [list cmake $here {*}$cmakeopt]
puts "Running: $cmd"
if { !$dryrun} {
	if { [catch {exec 2>@stderr >@stdout {*}$cmd} result] } {
		puts "CONFIGURE: cmake reported error: $result"
	}
} else {
	puts "(not really - dry run)"
}
