#!/bin/sh
# This is a Tcl/Tk script to be interpreted by tclsh (>=8.3): \
exec tclsh "$0" "$@"

#  instupdate - install GPSMan updates in a Unix/Linux system
#
#  Copyright (c) 2004 Miguel Filgueiras (mig@ncc.up.pt) / Universidade do Porto
#
#    This program is free software; you can redistribute it and/or modify
#      it under the terms of the GNU General Public License as published by
#      the Free Software Foundation; either version 2 of the License, or
#      (at your option) any later version.
#
#      This program 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 General Public License for more details.
#
#      You should have received a copy of the GNU General Public License
#      along with this program.
#
# Last change:  29 January 2004

# after unpacking the update archive:
#   cd util
#   instupdate.tcl [-n]

############# NO CONFIGURATION NEEDED

if { $tcl_platform(platform) != "unix" } {
    puts "This script needs utilities only available on Unix/Linux"
    exit 1
}

if { $argv == "-n" } {
    set DEBUG 1
} elseif { $argv != "" } {
    puts stderr "Usage: instupdate.tcl [-n]"
    puts stderr "  option -n prevents any change in the installed files"
    exit 1
} else { set DEBUG 0 }

if { $env(USER) == "root" } {
    set rexec 1
} else { set rexec 0 }

proc FindValues {vars file} {
    # find out values in first "set ... ..." instruction in $file for
    #  each variable in $vars
    # the order in the list must be the order in the file
    # return list of values aligned with $vars
    # could not use grep because of space being taken as argument separator

    set f [open $file r]
    set var [lindex $vars 0] ; set vars [lreplace $vars 0 0]
    set vals ""
    while { ! [eof $f] } {
	gets $f line
	if { [regexp "^(\\t| )*set $var (.+)\$" $line m m val] } {
	    lappend vals [string trim $val " \t"]
	    if { $vars == "" } {
		close $f
		return $vals
	    }
	    set var [lindex $vars 0] ; set vars [lreplace $vars 0 0]
	}
    }
    puts stderr "No definition of $var in $file"
    exit 1
}

proc SetValues {vars vals file tmp} {
    # change value in first "set" instruction in $file for each variable
    #  in $vars
    #  $vals is list of values aligned with $vars
    #  $tmp is path to directory to use for temporary files
    # the order in the list must be the order in the file
    # not using sed because of problems with repeated replacements
    global DEBUG

    set f [open $file r]
    set tf $tmp/TMPgiup-[clock seconds]
    set out [open $tf w]
    set var [lindex $vars 0] ; set vars [lreplace $vars 0 0]
    set val [lindex $vals 0] ; set vals [lreplace $vals 0 0]
    while { ! [eof $f] } {
	gets $f line
	if { $var != "" && \
		[regexp "^(\\t| )*set $var (.+)\$" $line m prefix m] } {
	    puts $out "${prefix}set $var $val"
	    set var [lindex $vars 0] ; set vars [lreplace $vars 0 0]
	    set val [lindex $vals 0] ; set vals [lreplace $vals 0 0]	    
	} else { puts $out $line }
    }
    close $f
    close $out
    if { $var != "" } {
	puts stderr "No definition of $var in $file"
	file delete -force $tf
	exit 1
    }
    if { ! $DEBUG } {
	file rename -force $tf $file
    } else {
	puts "DEBUG: file rename -force $tf $file"
    }
    return
}

# start

set wd [pwd]

if { [set bwd [file tail $wd]] != "util" } {
    puts stderr "After unpacking the update archive, cd to the util directory"
    puts stderr "Usage: inst_update"
    exit 1
}

set ugd "../gmsrc"

if { ! [file isdirectory $ugd] } {
    puts stderr "gmsrc directory from update archive not found"
    puts stderr "After unpacking the update archive, cd to the util directory"
    exit 1
}

## check versions
# find update version in line "Update to GPSMan version VERSION"

if { [catch {set uv [exec grep "GPSMan version" $ugd/UPDATE]}] } {
    puts stderr "Cannot execute grep $ugd/UPDATE"
    exit 1
}

if { ! [regexp {GPSMan version (.+)$} $uv x uv] } {
    puts stderr "Bad format of UPDATE file"
    exit 1
}

if { [catch {set iv [exec gpsman show version]}] } {
    if { $rexec } {
	puts "Will not compare installed version with that of update"
	set iv $uv
	set rexec 0
    } else {
	puts stderr "GPSMan not installed (or very old version)"
	exit 1
    }
} else { set rexec 1 }

if { $uv != $iv } {
    puts stderr "GPSMan installed version ($iv) not that of the update ($uv)"
    exit 1
}

## find installed executable to find out path to installed source directory

set iex ""

if { [catch {set iex [exec which gpsman]}] && \
	! [catch {set exs [exec whereis gpsman]}] } {
    foreach f $exs {
	if { ! [file isdirectory $f] && [file executable $f] } {
	    set iex $f
	    break
	}
    }
}

if { $rexec } {
    if { $iex == "" || [catch {set  v [exec $iex show version]}] || \
	    $v != $iv } {
	puts -nonewline "Absolute path to gpsman executable? "
	flush stdout
	gets stdin iex
	if { [file pathtype $iex] != "absolute" || \
		[catch {set  v [exec $iex show version]}] || $v != $iv } {
	    puts stderr "Bad path"
	    exit 1
	}
    } elseif { $DEBUG } { puts "DEBUG: using $iex as GPSMan executable" }
} elseif { $iex == "" } {
    puts -nonewline "Absolute path to gpsman executable? "
    flush stdout
    gets stdin iex
    if { [file pathtype $iex] != "absolute" } {
	puts stderr "Bad path"
	exit 1
    }
} elseif { $DEBUG } { puts "DEBUG: using $iex as GPSMan executable" }

set isd [FindValues SRCDIR $iex]

if { ! [file isdirectory $isd] || ! [file exists $isd/wrtdials.tcl] } {
    puts -nonewline "Absolute path to the GPSMan source directory?"
    flush stdout
    gets stdin isd
    if { [file pathtype $isd] != "absolute" || \
	    ! [file isdirectory $isd] || ! [file exists $isd/wrtdials.tcl] } {
	puts stderr "Bad path"
	exit 1
    }
} elseif { $DEBUG } { puts "DEBUG: using $isd as installed source directory" }

if { [file exists [set uex $ugd/gpsman.tcl]] } {
    ## editing updated executable (if any) to set crucial variables to
    #   the values in the installed executable
    #  assume each set instruction still has a single line with single spaces
    #   surrounding the variable name
    #  assume the order of in which these variables are set is as follows:
    #   DEFSPORT, USERDIR, USEROPTIONS, PRINTCMD, SRCDIR
    #   and that the values for Unix-like systems appear before than those
    #   for other systems

    puts "Making backup copy of $iex to $isd/gpsman.tcl-old"
    # take care of links
    set fiex $iex
    while { [file type $fiex] == "link" } {
	if { [file pathtype [set tgt [file link $fiex]]] == "relative" } {
	    set fiex [file join [file dirname $fiex] $tgt]
	} else { set fiex $tgt }
    }
    if { ! $DEBUG } {
	file copy -force $fiex $isd/gpsman.tcl-old
    } else {
	puts "DEBUG: file copy -force $fiex $isd/gpsman.tcl-old"
    }

    puts "The following variables in $iex will be preserved:"
    puts "\tSRCDIR  \t$isd"
    set vars "DEFSPORT USERDIR USEROPTIONS PRINTCMD"
    set vals [FindValues $vars $iex]
    foreach v $vars val $vals {
	puts "\t$v  \t$val"
    }
    puts "Preserving any other change to $iex must be made by hand!"
    if { ! $DEBUG } {
	file copy -force $ugd/gpsman.tcl $fiex
    } else {
	puts "DEBUG: file copy -force $ugd/gpsman.tcl $fiex"
    }
    lappend vars SRCDIR ; lappend vals $isd
    SetValues $vars $vals $fiex .
    if { ! $DEBUG } {
	file attributes $fiex -permissions 0755
    } else {
	puts "DEBUG: file attributes $fiex -permissions 0755"
    }
}

# other source files and icons

puts "Copying updated files to $isd..."

foreach f [glob $ugd/*.tcl] {
    if { $f != "$ugd/gpsman.tcl" } {
	if { ! $DEBUG } {
	    file copy -force $f $isd
	    file attributes $isd/[file tail $f] -permissions 0644
	} else {
	    puts "DEBUG: file copy -force $f $isd"
	    puts "DEBUG: file attributes $isd/[file tail $f] -permissions 0644"
	}
    }
}

if { [file exists $ugd/gmicons] } {
    foreach f [glob $ugd/gmicons/*] {
	if { ! $DEBUG } {
	    file copy -force $f $isd/gmicons
	    file attributes $isd/gmicons/[file tail $f] -permissions 0644
	} else {
	    puts "DEBUG: file copy -force $f $isd/gmicons"
	    puts \
	 "DEBUG: file attributes $isd/gmicons/[file tail $f] -permissions 0644"
	}
    }
}

# utilities

set uud $ugd/util
if { [file exists $uud] } {
    set iud ""
    foreach d "$isd $isd/util" {
	if { [file exists $d] && [file isdirectory $d] && \
		[file exists $d/exerciser.tcl] } {
	    set iud $d
	    break
	}
    }
    if { $iud == "" } {
	puts -nonewline "Absolute path to util directory? "
	flush stdout
	gets stdin iud
	if { [file pathtype $iud] != "absolute" || \
		! [file isdirectory $iud] } {
	    puts stderr "Bad path"
	    exit 1
	}
    }
    puts "Copying updated utilities to $iud..."
    foreach f [glob $uud/*] {
	if { ! $DEBUG } {
	    file copy -force $f $iud
	    file attributes $iud/[file tail $f] -permissions 0755
	} else {
	    puts "DEBUG: file copy -force $f $iud"
	    puts "DEBUG: file attributes $iud/[file tail $f] -permissions 0755"
	}
    }
    puts "The utility  programs may also require configuration by hand!"
}

puts "Finished"

exit 0



