#
# $Source: /home/nlfm/Working/Zircon/Released/installer/RCS/unix.tcl,v $
# $Date: 1997/01/14 13:47:17 $
# $Revision: 1.18.1.23 $
#
# ----------------------------------------------------------------------
#   AUTHOR:  Lindsay Marshall <lindsay.marshall@newcastle.ac.uk>
# ----------------------------------------------------------------------
# Copyright 1996 The University of Newcastle upon Tyne (see COPYRIGHT)
# ======================================================================
#
package provide unix 1.18
#
proc install {} {
#
    package require support
    package require -exact unixfile 1.18.[info tclversion]
#
    global Type types Lib Bin CC Version Patchlevel Wish types cflags\
      libs share SCflag GCC SLDflag CFlags TIDir
#
    set types {AIX Alpha FreeBSD HP-UX IRIX Linux {SunOS 4} {SunOS 5} UNIX_SV}
#
    array set cflags {
	HP-UX		{+O3 -Aa -D_HPUX_SOURCE}
    }

    array set scflags {
	HP-UX		{+z}
	IRIX		{-KPIC}
	FreeBSD		{-fpic}
	SCO		{-Kpic -belf}
	{SunOS 4}	{-PIC}
	{SunOS 5}	{-KPIC}
	UNIX_SV		{-KPIC}
    }
#
    array set libs {
	UNIX_SV		{-lsocket -lnsl}
	IRIX		{-lnsl}
	{SunOS 5}	{-lsocket -lnsl}
    }
#
    array set share {
	{SunOS 5}	{-G -z text}
	UNIX_SV		{-G -z text}
	IRIX		{-shared -rdata_shared}
	AIX		{-bhalt:4 -bM:SRE -bE:lib.exp -H512 -T512}
	FreeBSD		{-Bshareable -x}
	SCO		{-G}
	Linux		{-shared}
    }
#
    source [file join installer zircon.tcl]
    set Type {}
    set Lib {}
    set Bin {}
    set CC {}
    set GCC 1
    set SCflag {}
    set SLDflag {}
    set CFlags {}
    set Wish {}
    set TIDir {}
    catch {source install.in}
    checkSCF
#
# Handle OS name change for Suns
#
    switch $Type {
	SunOS { set Type {SunOS 4} }
	Solaris { set Type {SunOS 5} }
    }
#
    set w [toplevel .inst]
    wm title $w {Zircon Installer}
    wm resizable $w 1 0 
    grid columnconfigure $w 1 -weight 1
    label $w.version -text "Zircon Version $Version\
      patchlevel $Patchlevel"
    grid $w.version -columnspan 2 -pady 5
#
# System Type
#
    menubutton $w.type -text {System Type} -menu $w.type.menu -relief raised
    menu $w.type.menu -tearoff 0
    foreach x $types {
	$w.type.menu add command -label $x -command "set Type $x"
    }
    entry $w.typeentry -textvariable Type -state disabled -width 30
    getType
    set i 0
    gridIt $w type [incr i]
#
# Zircon library directory
#
    button $w.lib -text {Library Directory}
    entry $w.libentry -textvariable Lib
    getLib
    gridIt $w lib [incr i]

#
# Zircon binary directory
#
    button $w.bin -text {Binary Directory}
    entry $w.binentry -textvariable Bin
    getBin
    gridIt $w bin [incr i]
#
# Wish
#
    button $w.wish -text {Tcl/Tk Interpreter}
    entry $w.wishentry -textvariable Wish
    getWish
    gridIt $w wish [incr i]
#
# C compiler
#
    button $w.cc -text {C Compiler}
    entry $w.ccentry -textvariable CC
    getCC
    gridIt $w cc [incr i]
#
# C compiler Flags
#
    button $w.flg -text {C Compiler Flags}
    entry $w.flgentry -textvariable CFlags
    gridIt $w flg [incr i]
#
# C Shared compile
#
    button $w.scf -text {C Shared code}
    entry $w.scfentry -textvariable SCflag
    gridIt $w scf [incr i]
#
# Tcl.h include directory
#
    button $w.tid -text {tcl Header Directory}
    entry $w.tidentry -textvariable TIDir
    gridIt $w tid [incr i]
#
# Shared load 
#
    button $w.dl -text {Shared code loading}
    entry $w.dlentry -textvariable SLDflag
    gridIt $w dl [incr i]
#
# Info
#
    grid [label $w.info] -columnspan 2 -sticky ew
#
# Buttons
#
    frame $w.btn
    button $w.btn.quit -text Quit -command Quit -width 12
    button $w.btn.install -text Install -command Go -width 12
    grid $w.btn.quit $w.btn.install
    grid $w.btn -columnspan 2 -sticky ew
}
#
proc getType {} {
    global tcl_platform Type
    set Type $tcl_platform(os)
    switch $Type {
	SunOS {
	    switch -glob $tcl_platform(osVersion) {
		4* { set Type {SunOS 4} }
		5* { set Type {SunOS 5} }
	    }
	}
    }
}
#
proc getLib {} {
    global Lib
    switch {} $Lib {set Lib /usr/local/lib/zircon}
}
#
proc getWish {} {
    global Wish
    switch {} $Wish {set Wish [findWish]}
}
#
proc getBin {} {
    global Bin env Lib Wish
    switch {} $Bin {} default return
    foreach x [split $env(PATH) :] {
	set z [file join $x zircon]
	if {[file exists $z]  && [file executable $z]  && \
	  ![file isdirectory $z]} {
	    set Bin $x
	    if ![catch {open $z r} fd] {
		gets $fd wish
		set Wish [string range $wish 2 end]
		gets $fd lib
		close $fd
		set Lib [lindex $lib 2]	
	    }
	    return
	}
    }
    set Bin /usr/local/bin
}
#
proc getCC {} {
    global CC GCC SCflag CFlags Type SLDflag share scflags
    switch {} $CC {} default return
    set CFlags -O
    catch {set CFlags $cflags($Type)}
    switch {} [set CC [searchX gcc]] {
	set GCC 0
	set CC [searchX cc]
	set SCflag -pic
	if [info exists scflags($Type)] { set SCflag $scflags($Type) }
    } default {
	set GCC 1
	set SCflag -fPIC
    }
    if [info exists share($Type)] {
	set SLDflag $share($Type)
    }
}
#
proc searchX {prog} {
    global env
    switch [file pathtype $prog] {
    relative {
	    foreach x [split $env(PATH) :] {
		if [file exists [file join $x $prog]] {
		    return [file join $x $prog]
		}
	    }
	}
    }
    return {}
}
#
proc findWish {} {
    global env
    foreach x [split $env(PATH) :] {
	foreach y {wish8.0 wish4.2 wish4.1 wish wishx} {
	    if [file exists [set f [file join $x $y]]] {
		return $f
	    }
	}
    }
    return {}
}
#
proc prog {file to} {
    zinfo "Compiling $file..."
    global CC libs Type CFlags
    set to [dmake [set dt [file dirname $file]] $to]
    set lb {}
    if [info exists libs($Type)] { set lb $libs($Type) }
    set tg [file rootname [file join $to [file tail $file]]]
    if [catch {eval exec $CC $CFlags -o $tg $file $lb} msg] {
	fail "Compilation of $file failed - $msg"
    }
}
#
proc checkSCF {} {
    global SCflag CC GCC CFlags SLDflag Type share Type

    switch -glob $CC {
	/*/gcc -
	gcc { set SCflag -fPIC ; set GCC 1}
	default {
	    switch {} $SCflag {
		if [info exists share($Type)] {
		    set SCflag $share($Type)
		} {
		    set SCflag -pic
		}
	    }
	    set GCC 0
	}
    }
    if [info exists share($Type)] { set SLDflag $share($Type) }
}
#
proc libr {file to} {
    zinfo "Compiling $file..."
    global CC Type SCflag CFlags SLDflag TIDir
    checkSCF
    set cfl "$CFlags $SCflag"
    switch {} $TIDir {} default {append cfl " -I$TIDir"}
    set to [dmake [set dt [file dirname $file]] $to]
    if [catch {eval exec $CC $cfl -c $file} msg] {
	fail "Compile $file failed - $msg"
    }
    zinfo "Linking $file..."
    if [catch {eval exec ld $SLDflag \
      -o [file join $to lib[file tail $dt][info sharedlibextension]]\
      [file rootname [file tail $file]].o} msg] {
	fail "Link $file failed - $msg"
    }
    filedelete [file rootname [file tail $file]].o
}

#
proc makeLibrary {} {
    global Lib Manifest Index Patchlevel Version TIDir
    switch {} $TIDir {} default {
	if ![file exists [set TIDir [fixPath $TIDir]]] {
	    fail "Directory \"$TIDir\" does not exist"
	    return 0
	}
	if ![file isdirectory $TIDir] {
	    fail "\"$TIDir\" is not a directory"
	    return 0
	}
	if ![file exists [file join $TIDir tcl.h]] {
	    fail "tcl.h does not exist in \"$TIDir\""
	    return 0
	}
    }
    if [file exists [set Lib [fixPath $Lib]]] {
	if [file exists [set fn [file join $Lib installed]]] {
	    set fd [open $fn r]
	    gets $fd line
	    close $fd
	    set ov [lindex $line 0]
	    set op [lindex $line 1]
	    set ext -$Version$Patchlevel
	    switch $ov $Version {
		switch $op $Patchlevel {
		   if [askUser {Same Version} "You are installing version\
$Version $Patchlevel again.

Overwrite the existing version?"] { set ext {} }
		}
	    }
	} {
	    set ext .old
	}
	switch {} $ext {} default {
	    if [catch {filerename $Lib $Lib$ext} msg] {
		if ![askUser Continue "Cannot rename $Lib to \
		  $Lib.old - \"$msg\"

Continue?"] { return 0 }
	    }
	    if {[catch {filemkdir $Lib} msg]} {
		fail "Cannot make directory $Lib - \"$msg\""
		return 0
	    }
	}
    } \
    elseif {[catch {filemkdir $Lib} msg]} {
	fail "Cannot make directory $Lib - \"$msg\""
	return 0
    }
    foreach x [lsort [array names Manifest]] { 
	switch {} $Manifest($x) {} default {$Manifest($x) $x $Lib }
    }
    foreach x $Index {
	zinfo "Making package index for $x..."
	pkg_mkIndex [file join $Lib $x] *.tcl *[info sharedlibextension]
    }
    set fd [open [file join $Lib installed] a]
    puts $fd "$Version $Patchlevel {[clock format [clock seconds]]}"
    close $fd
    return 1
}
#
proc makeBinary {} {
    zinfo "Making zircon..."
    global Bin Lib Version Patchlevel Wish
    if ![file exists [set Bin [fixPath $Bin]]] {
	if [catch {filemkdir $Bin} msg] {
	    fail "Cannot create directory \"$Bin\" - $msg"
	    return 0
	}
    } \
    elseif {![file isdirectory $Bin]} {
	fail "\"$Bin\" is not a directory"
	return 0
    }
    set tf [file join $Bin zircon]
    if [file exists $tf] {
	if [catch {filerename $tf $tf.old} msg] {
	   fail "Cannot rename previous zircon executable - \"$msg\""
	   return 0
	}
    }
    if [catch {open $tf w 0755} fd] {
	fail "Cannot create zircon executable - \"$fd\""
	if [file exists $tf.old] {
	    file rename -force $tf.old $tf
	}
	return 0
    }
    puts $fd "#!$Wish"
    puts $fd "set zircon(lib) {$Lib}"
    puts $fd "#
proc zVersion {} {
    global zircon
    array set zircon {
	version		$Version
	patchlevel	$Patchlevel
    }
}
#"
    puts $fd [info body zircon]
    close $fd
    return 1
}
