############################################################################
#
#	File:     ipatch.icn
#
#	Subject:  Program to patch iconx path in executable
#
#	Author:   Gregg M. Townsend
#
#	Date:     November 15, 2000
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
#  Usage:  ipatch file path
#
#     Ipatch changes the path to iconx, the Icon interpreter, that is
#  embedded in an Icon executable file under Unix.  Icon 9.4 headers are
#  rewritten in the same form.  Because headers from earlier versions of
#  Icon contain no room for expansion, they are rewritten in a different
#  form to accommodate a possibly-longer path.
#
############################################################################
#
#  Requires:  Unix
#
############################################################################

procedure main(args)
   local fname, path, f, header, hlength, pfx

   if *args ~= 2 then
      stop("usage: ", &progname, " file iconx")
   fname := get(args)
   path := get(args)

   f := open(fname, "rwu") | stop("cannot open ", fname, " for writing")
   header := reads(f, 1000) | stop(fname, ": empty file")

   header ? {
     (tab(find("\n[executable Icon binary follows]\n")) & tab(find("\f\n\0"))) |
         stop(fname, ": not an Icon executable")
      hlength := &pos - 1
      tab(1)
      if pfx := tab(find("IXBIN=") + 6) then {
         # Icon 9.4 or later binary
         tab(upto('\n'))
         header := pfx || path || tab(hlength + 1)
         }
      else {
         # Icon 9.3 or earlier binary
         header := "#!/bin/sh" ||
            "\n" ||
            "\nexec ${ICONX-" || path || "} $0 ${1+\"$@\"}" ||
            "\n\n\n\n\n" ||
            "\n[executable Icon binary follows]" ||	# must appear exactly
            "\n"
         }
      }

   if *header + 3 > hlength then
      stop("cannot patch: path is too long to fit")

   if not close(open(path)) then
      write(&errout, "warning: cannot open ", path, "; patching anyway")

   seek(f, 1) | stop("cannot reposition ", fname)
   writes(f, left(header, hlength)) | stop("write failed")
end
