;;; -*-Emacs-Lisp-*-

;; SKK-MK: installer for SKK.
;; Copyright (C) 1999, 2000 Mikio Nakajima <minakaji@osaka.email.ne.jp>

;; Author: Mikio Nakajima <minakaji@osaka.email.ne.jp>
;; Maintainer: SKK Development Team <skk@ring.gr.jp>
;; Version: $Id: SKK-MK,v 1.67 2000/12/30 08:52:09 minakaji Exp $
;; Last Modified: $Date: 2000/12/30 08:52:09 $

;; Commentary
;;
;; Those values of variables below are default configurations.
;; If you would like to change some of those, you should edit SKK-CFG.
;;
;;              DO NOT EDIT THIS FILE DIRECTLY!
;;
;; Please note that all variables specified in the command line
;; overwrite ones defined in SKK-MK and SKK-CFG.
;;
;; Variable sections are all three parts.  GENERIC VARIABLE section,
;; NON-PACKAGE INSTALL RELATED VARIABLE section, and PACKAGE INSTALL
;; RELATED VARIABLE section.
;;
;; You can confirm target directories without an actual installation
;; by M-x SKK-MK-what-where or M-x SKK-MK-what-where-package after
;; load this program.

;;; Code:
;; tinyinstall.el is independent of APEL.
(require 'tinyinstall (expand-file-name "./tinyinstall"))

;;;; User variables to control SKK-MK.
(defvar SKK-MK-debugging nil "*Non-nil means making verbose output.")

;;;; Load configuration file.
;; load user custom file if exists.
(load (expand-file-name "./SKK-CFG") t nil nil)

;;;; load-path related.
;; `install-prefix' is defined in tinyinstall.el.
;; Maybe it is `/usr/local', if you use UNIX.
(defvar EMU_PREFIX
  (or (getenv "EMU_PREFIX")
      (if (or (featurep 'xemacs)
	      (and (fboundp 'set-buffer-multibyte)
		   (subrp (symbol-function 'set-buffer-multibyte))))
	  "emu"
	"")))
(defvar PREFIX (or (getenv "PREFIX") install-prefix))
(defvar LISPDIR
  (let ((dir (expand-file-name
	      (or (getenv "LISPDIR")
		  (cond ((eq system-type 'windows-nt)
			 (expand-file-name "site-lisp" PREFIX))
			((eq system-type 'ms-dos)
			 (expand-file-name "site-lis" PREFIX))
			(t
			 (install-detect-elisp-directory PREFIX)))))))
    (if (file-exists-p dir)
	(progn
	  ;; default-load-path takes effect for detecting directory.
	  (setq default-load-path (tinyinstall-add-load-path dir default-load-path))
	  dir))))
(defvar VERSION_SPECIFIC_LISPDIR
  (let ((dir (expand-file-name
	      (or (getenv "VERSION_SPECIFIC_LISPDIR")
		  (cond ((eq system-type 'windows-nt)
			 (expand-file-name "site-lisp" PREFIX))
			((eq system-type 'ms-dos)
			 (expand-file-name "site-lis" PREFIX))
			(t
			 (install-detect-elisp-directory PREFIX nil 'version-specific)))))))
    (if (file-exists-p dir) dir)))
(defvar APEL_SPECIFIC_LISPDIR (let ((dir (getenv "APEL_SPECIFIC_LISPDIR")))
				(and dir (file-exists-p dir) (expand-file-name dir))))
(defvar ADDITIONAL_LISPDIR nil)

;; in case of defining these variables in SKK-CFG.
(and APEL_SPECIFIC_LISPDIR
     (setq APEL_SPECIFIC_LISPDIR (expand-file-name APEL_SPECIFIC_LISPDIR)))
(and LISPDIR (setq LISPDIR (expand-file-name LISPDIR)))
(and VERSION_SPECIFIC_LISPDIR
     (setq VERSION_SPECIFIC_LISPDIR (expand-file-name VERSION_SPECIFIC_LISPDIR)))

;; searching APEL installed directory...
(if (and LISPDIR (file-exists-p LISPDIR))
    (setq load-path (tinyinstall-add-load-path LISPDIR load-path)))

(let* ((emutmp)
       (apeldir
	(cond ((and APEL_SPECIFIC_LISPDIR (file-exists-p APEL_SPECIFIC_LISPDIR)
		    APEL_SPECIFIC_LISPDIR))
	      ((file-exists-p (expand-file-name "apel" LISPDIR))
	       (expand-file-name "apel" LISPDIR))
	      ;; Unix
	      ((file-exists-p (expand-file-name "../../site-lisp/apel" data-directory))
	       (expand-file-name "../../site-lisp/apel" data-directory))
	      ;; Mule for Windows.
	      ((and
		;; Following two lines identifies Mule for Windows, but are there
		;; any other Emacsen that have the same directory structure?
		;;(featurep 'mule) (eq system-type 'windows-nt)
		;;(= emacs-major-version 19)
		(file-exists-p (expand-file-name "../site-lisp/apel" exec-directory)))
	       (expand-file-name "../site-lisp/apel" exec-directory))))
       (emudir
	(cond ((and
		VERSION_SPECIFIC_LISPDIR
		(setq emutmp (expand-file-name EMU_PREFIX VERSION_SPECIFIC_LISPDIR))
		(cond ((and (file-exists-p emutmp)
			    (not (string= emutmp VERSION_SPECIFIC_LISPDIR))
			    (file-exists-p (expand-file-name "emu.el" emutmp))))
		      ((and
			(string= EMU_PREFIX "")
			;; try again with not standard emu directory.
			(setq emutmp (expand-file-name "emu" VERSION_SPECIFIC_LISPDIR))
			(not (string= emutmp VERSION_SPECIFIC_LISPDIR))
			(file-exists-p emutmp)
			(file-exists-p (expand-file-name "emu.el" emutmp))))))
	       emutmp)
	      ((and
		apeldir
		(setq emutmp (expand-file-name (concat "../" EMU_PREFIX) apeldir))
		(cond ((and (file-exists-p emutmp)
			    (not (string= emutmp VERSION_SPECIFIC_LISPDIR))
			    (file-exists-p (expand-file-name "emu.el" emutmp))))
		      ((and
			(string= EMU_PREFIX "")
			;; try again with not standard emu directory.
			(setq emutmp (expand-file-name "../emu" apeldir))
			(not (string= emutmp VERSION_SPECIFIC_LISPDIR))
			(file-exists-p emutmp)
			(file-exists-p (expand-file-name "emu.el" emutmp))))))
	       emutmp))))
  (and emudir
       (setq load-path (tinyinstall-add-load-path emudir load-path)))
  (and apeldir
       (setq load-path (tinyinstall-add-load-path apeldir load-path))))

(setq load-path (cons (expand-file-name ".") load-path))

(and VERSION_SPECIFIC_LISPDIR
     (file-exists-p VERSION_SPECIFIC_LISPDIR)
     (setq load-path (tinyinstall-add-load-path
		      (expand-file-name VERSION_SPECIFIC_LISPDIR) load-path)))

(and ADDITIONAL_LISPDIR
     (file-exists-p ADDITIONAL_LISPDIR)
     (setq load-path (tinyinstall-add-load-path
		      (expand-file-name ADDITIONAL_LISPDIR) load-path)))

(if SKK-MK-debugging
    (progn
      (princ (format "APEL_SPECIFIC_LISPDIR=%s\n" APEL_SPECIFIC_LISPDIR))
      (princ (format "load-path=%s\n" load-path))))

;; After seaching APEL installed dirctory, require full set install.el.
(require 'poe)
(require 'install)

;; constants.
(defconst SKK-MK-texinfo-coding-system
  (cond ((or (featurep 'xemacs)
	     (and (boundp 'mule-version)
		  (or (string< "4.0" mule-version) (string< "3.0" mule-version))))
	 'junet)
	((boundp 'MULE)
	 *junet*)
	(t
	 nil)))

;; GENERIC VARIABLE.
(defvar DOCDIR (or (getenv "DOCDIR") "./doc"))
(defvar ETCDIR (or (getenv "ETCDIR") "./etc"))
(defvar DICDIR (or (getenv "DICDIR") "./dic"))
(defvar SKK_PREFIX (or (getenv "SKK_PREFIX") "skk"))
(defvar SKK_INFO (or (getenv "SKK_INFO") "skk.info"))
(defvar SKK_TEXIS (or (getenv "SKK_TEXIS") '("skk.texi")))
(defvar SKK_TUTORIALS (or (getenv "SKK_TUTORIALS")
			  '("SKK.tut" "SKK.tut.E" "NICOLA-SKK.tut")))
(defvar SKK_DICTIONARIES
  (or (getenv "SKK_DICTIONARIES")
      '("SKK-JISYO.L" "SKK-JISYO.M" "SKK-JISYO.S"
	"SKK-JISYO.JIS2" "SKK-JISYO.JIS3_4"
	"SKK-JISYO.pubdic+" "SKK-JISYO.edict"
	"SKK-JISYO.office.zipcode" "SKK-JISYO.zipcode")))
(defvar SKK_MODULES
  ;; $B$3$s$J$b$s%3%^%s%I%i%$%s$G;XDj$9$k?M$$$J$$$h$M!)(B
  (or (getenv "SKK_MODULES")
      (let ((list '(queue-m skk-macs skk-vars
			    skk skk-auto skk-autoloads skk-comp
			    skk-develop skk-gadget
			    skk-isearch skk-kakasi skk-kcode
			    skk-leim skk-look skk-num skk-obsolete
			    skk-cursor skk-server skk-tut skk-version
			    ;; EXPERIMENTAL
			    skk-abbrev skk-dcomp skk-annotation
			    skk-jisx0201 skk-rdbms skk-study
			    skk-tutcdef skk-tutcode skk-correct
			    skk-exsearch skk-exserv
			    ;; VIP 3.7
			    ;; vip
			    )))
	;; $B%P%$%H%3%s%Q%$%k;~$K(B X window $B$,(B initialize $B$5$l$F$$$J$$$H$$$&%(%i!<(B
	;; $B$K$J$k(B (;_;)$B!#(B
	;; yatex $B$_$?$$$K(B Window $B$r3+$$$F%P%$%H%3%s%Q%$%k$9$k$h$&$K$b$G$-$k$1$I!"(B
	;; no-window $B$N(B make $B%3%^%s%I$rJL$K:n$i$J$-$c$J$i$J$$$7!"LLE]$@$J(B...$B!#(B
        ;;(if (if (featurep 'xemacs)
        ;;        (eq (device-class (selected-device)) 'color)
        ;;      (x-display-color-p))
        ;;    (setq list (nconc list (list 'skk-cursor))))
	(cond ((featurep 'xemacs)
	       ;; XEmacs
	       (cond ((member "skk-leim" preloaded-file-list)
		      (setq list (nconc list (list 'skk-xm20_4))))
		     ((or (featurep 'gdbm) (featurep 'dbm) (featurep 'berkdb)
			  (featurep 'berkeley-db))
		      (setq list (nconc list (list 'skk-dbm)))))
	       (setq list (nconc list (list 'skk-xemacs))))
	      (t
	       ;; FSFmacs
	       (setq list (nconc list (list 'ccc)))
	       (and (eq emacs-major-version 21)
		      (setq list (nconc list (list 'skk-e21))))
	       (or (fboundp 'register-input-method)
		   (setq list (delq 'skk-leim list)))))
	;; skk-jisx0213.el
	(condition-case nil
	    (and (require 'jisx0213) (require 'un-define)
		 (setq list (nconc list (list 'skk-jisx0213))))
	  (error))
	;; skk-lookup.el
	(condition-case nil
	    ;; you might have to add lookup installed directory to `load-path'.
	    (and (let ((lookup-byte-compile t)) (require 'lookup))
                 (setq list (nconc list (list 'skk-lookup))))
	  (error))
	;; skk-viper.el
	(condition-case nil
	    (and (require 'viper) (setq list (nconc list (list 'skk-viper))))
	  (error))
	;;
	list)))

;; $B>C$5$J$/$H$b%$%s%9%H!<%k>e$OLdBj$,$J$$$,!"(Bwhat-where $B%$%s%9%H!<%k$5$l$J$$(B
;; $B%W%m%0%i%`$,I=<($5$l$k$N$rKI$0$?$a!"%H%C%W%G%#%l%/%H%j$K$J$$%W%m%0%i%`$O(B
;; $B>C$7$F$*$/!#(B
(let ((modules SKK_MODULES))
  (while modules
    (or 
     ;; skk-autoloads.el $B$O<+F0@8@.$5$l$k$N$G$^$@B8:_$7$J$$!#(B
     (eq (car modules) 'skk-autoloads)
     (file-exists-p (concat (symbol-name (car modules)) ".el"))
     (setq SKK_MODULES (delq (car modules) SKK_MODULES)))
    (setq modules (cdr modules))))

;; NON-PACKAGE INSTALL RELATED VARIABLE.
(defvar SKK_DATADIR
  (or (getenv "SKK_DATADIR")
      (expand-file-name SKK_PREFIX (expand-file-name "share" PREFIX))))
(defvar SKK_INFODIR
  (or (getenv "SKK_INFODIR")
      (and (getenv "INFOPATH")
 	   (progn (require 'info) (car Info-directory-list)))
      (expand-file-name "info" PREFIX)))
(defvar SKK_LISPDIR
  (or (getenv "SKK_LISPDIR")
      (and VERSION_SPECIFIC_LISPDIR
	   (expand-file-name SKK_PREFIX VERSION_SPECIFIC_LISPDIR))
      (and PREFIX 
           (expand-file-name SKK_PREFIX 
                             (install-detect-elisp-directory PREFIX)))))

;; PACKAGE INSTALL RELATED VARIABLE.
(defvar PACKAGEDIR
  (or (getenv "PACKAGEDIR")
      (if (boundp 'early-packages)
	  (let ((dirs
		 (append (if early-package-load-path early-packages)
			 (if late-package-load-path late-packages)
			 (if last-package-load-path last-packages)))
		dir)
	    (while (not (file-exists-p (setq dir (car dirs))))
	      (setq dirs (cdr dirs)))
	    dir))))
(defvar PACKAGE_INFODIR
  (or (getenv "PACKAGE_INFODIR") (expand-file-name "info" PACKAGEDIR)))
(defvar PACKAGE_DATADIR
  (or (getenv "PACKAGE_DATADIR")
      (expand-file-name SKK_PREFIX (expand-file-name "etc" PACKAGEDIR))))
(defvar PACKAGE_LISPDIR
  (or (getenv "PACKAGE_LISPDIR")
      (expand-file-name SKK_PREFIX (expand-file-name "lisp" PACKAGEDIR))))

(if SKK-MK-debugging (princ (format "SKK_MODULES=%s\n" SKK_MODULES)))

(defconst SKK_DAREDEVIL_NOT_USE '(skk-vip skk-foreword stack-m skk-cursor2 skk-cursor3))

;; This code is for skk-jisx0201.el.
(cond ((fboundp 'make-translation-table) ;; Emacs 20.3 or later
       (setq standard-translation-table-for-decode
	     (make-translation-table nil)))
      ((fboundp 'make-unification-table) ;; Emacs 20.2
       (setq standard-character-unification-table-for-decode
	     (make-unification-table nil))))

;; Work around for Emacs 18.
(if (= 18 emacs-major-version)
    (progn
      (setq SKK_INFO nil)
      (let ((list '(ccc skk-cursor skk-isearch skk-jisx0201 skk-study)))
	(while list
	  (setq SKK_MODULES (delq (car list) SKK_MODULES))
	  (setq list (cdr list))))
      (setq SKK_MODULES
	    (nconc SKK_MODULES
		   '(skk-e18 skk-is-n)))
      (condition-case nil
	  (load "bytecomp-runtime")
	(error))
      ;;
      (require 'skk-e18 (expand-file-name "skk-e18.el" default-directory))))

;;; [FUNCTIONS]
(defun SKK-MK-make-setup-file (spec)
  ;; SPEC $B$O8rBe%j%9%H!#(B
  (with-temp-buffer
    (save-excursion
      (insert-file-contents "skk-setup.el.in")
      (goto-char (point-min))
      (when (looking-at ";;; -\\*- emacs-lisp -\\*-")
	(delete-region (point) (progn (forward-line 1) (point))))
      (when (search-forward ";;; skk-setup.el --- Initial setup for SKK")
	(forward-char 1)
	(insert ";; This file was generated automatically by SKK-MK at "
		(current-time-string)
		"\n"))
      (while spec
	(goto-char (point-min))
	(while (re-search-forward (concat "^;;[^@]+\\(" (car spec) "\\)")
				  nil t nil)
	  (delete-region (match-beginning 1) (match-end 1))
	  (insert (nth 1 spec))
	  (beginning-of-line)
	  (while (looking-at ";")
	    (delete-char 1)))
	(setq spec (nthcdr 2 spec)))
      (write-region (point-min) (point-max) "skk-setup.el"))))

(defun SKK-MK-server-installed-p (&optional server ps conf)
  (or
   (and
    (or ps (setq ps (exec-installed-p "ps")))
    (with-temp-buffer
      (and (eq 0 (call-process
		  ps nil
		  (current-buffer) nil
		  (if (eq 0 (call-process ps nil nil nil "-dfj"))
		      ;; System V
		      "-e"
		    ;; BSD
		    "-ax")))
	   (progn
	     (goto-char (point-min))
	     (re-search-forward
	      (or (and server (file-name-nondirectory server)) "skkserv")
	      nil t)))))
   (and
    (file-readable-p (or conf (setq conf "/etc/inetd.conf")))
    (with-temp-buffer
      (insert-file-contents conf)
      (goto-char (point-min))
      (re-search-forward "^skkserv" nil t)))))

(defvar SKK_SET_JISYO
  (let* ((set_jisyo (or (getenv "set_jisyo") (getenv "SET_JISYO")))
	 (flag
	  (cond ((not (stringp set_jisyo))
		 'fuzzy)
		((member (downcase set_jisyo) '("yes" "1" "t" "y"))
		 t)
		((member (downcase set_jisyo) '("no" "0" "-1" "nil" "n"))
		 nil)
		(t
		 'fuzzy))))
    (if (eq flag 'fuzzy)
	(not (SKK-MK-server-installed-p))
      flag)))

(defun SKK-MK-compile ()
  (let (enable-local-eval)
    (SKK-MK-generate-autoloads-el)
    (when (and (= 18 emacs-major-version)
	       (< emacs-minor-version 59))
      ;; Emacs 18.55, etc.
      (with-temp-buffer
	(insert-file-contents (expand-file-name "SKK-MK"
						default-directory))
	(eval-current-buffer)))
    (require 'skk-autoloads
	     (expand-file-name "skk-autoloads.el" default-directory))
    (require 'skk (expand-file-name "skk.el" default-directory))
    (compile-elisp-modules SKK_MODULES (expand-file-name "."))))

(defun SKK-MK-compile-info ()
  (and SKK_INFO
       (if (or (not (file-exists-p (expand-file-name SKK_INFO DOCDIR)))
	       (file-newer-than-file-p (expand-file-name (car SKK_TEXIS) DOCDIR)
				       (expand-file-name SKK_INFO DOCDIR)))
	   (SKK-MK-texinfo-format SKK_TEXIS))))

(defun SKK-MK-compile-package ()
  (SKK-MK-generate-autoloads-el-package)
  (require 'skk (expand-file-name "skk.el" default-directory))
  (autoload 'custom-add-loads "cus-load")
  (compile-elisp-modules SKK_MODULES (expand-file-name ".")))

(defun SKK-MK-install ()
  (SKK-MK-install-elc)
  (SKK-MK-install-info))

(defun SKK-MK-install-elc ()
  (let ((dics SKK_DICTIONARIES)
	;;standard-output
	delete-target exists spec)
    ;; make target directories.
    (setq DOCDIR (expand-file-name DOCDIR)
	  ETCDIR (expand-file-name ETCDIR)
	  DICDIR (expand-file-name DICDIR))
    (or (file-exists-p SKK_LISPDIR)
	(make-directory SKK_LISPDIR t))
    (or (file-exists-p SKK_DATADIR)
	(make-directory SKK_DATADIR t))
    ;; delete already installed unnecessary files.
    (while SKK_DAREDEVIL_NOT_USE
      (setq SKK_MODULES (delq (car SKK_DAREDEVIL_NOT_USE) SKK_MODULES)
	    delete-target (expand-file-name
			   (concat (prin1-to-string (car SKK_DAREDEVIL_NOT_USE))
				   ".el")
			   SKK_LISPDIR)
	    SKK_DAREDEVIL_NOT_USE (cdr SKK_DAREDEVIL_NOT_USE))
      (and (file-exists-p delete-target) (delete-file delete-target))
      (setq delete-target (concat delete-target "c"))
      (and (file-exists-p delete-target) (delete-file delete-target)))
    ;; install Emacs Lisp programs.
    (SKK-MK-compile)
    (install-elisp-modules SKK_MODULES "." SKK_LISPDIR)
    (delete-file "./skk-autoloads.el")
    ;; make skk-setup.el.
    (while dics
      (when (file-exists-p (expand-file-name (car dics) DICDIR))
	(setq exists (cons (car dics) exists)))
      (setq dics (cdr dics)))
    (setq SKK_DICTIONARIES exists)
    ;; move existing largest dictionay to car of `SKK_DICTIONARIES'.
    (and (member "SKK-JISYO.M" SKK_DICTIONARIES)
	 (setq SKK_DICTIONARIES
	       (cons "SKK-JISYO.M" (delete "SKK-JISYO.M" SKK_DICTIONARIES))))
    (and (member "SKK-JISYO.L" SKK_DICTIONARIES)
	 (setq SKK_DICTIONARIES
	       (cons "SKK-JISYO.L" (delete "SKK-JISYO.L" SKK_DICTIONARIES))))
    (if SKK_TUTORIALS
	(setq spec (append spec (list "@TUT@"
				      (expand-file-name
				       (car SKK_TUTORIALS) SKK_DATADIR)))))
    (if SKK_DICTIONARIES
	(progn
	  (setq spec
		(append spec
			(list "@AUXDIC@"
			      (expand-file-name
			       (car SKK_DICTIONARIES) SKK_DATADIR))))
	  (and SKK_SET_JISYO
	       (setq spec
		     (append spec
			     (list
			      "@DIC@"
			      (expand-file-name (car SKK_DICTIONARIES) SKK_DATADIR))))))
      ;; when dictionaries do not exist in ./dic subdirectory, check
      ;; already installed dictionary and detect largest one to setup
      ;; skk-setup.el.in.
      (setq dics '("SKK-JISYO.L" "SKK-JISYO.M" "SKK-JISYO.S"))
      (while (and dics
		  (not
		   (file-exists-p (expand-file-name (car dics) SKK_DATADIR))))
	(setq dics (cdr dics)))
      (if dics
	  (progn
	    (setq spec
		  (append spec
			  (list "@AUXDIC@"
				(expand-file-name (car dics) SKK_DATADIR))))
	    (and SKK_SET_JISYO
		 (setq spec
		       (append spec (list "@DIC@"
					  (expand-file-name
					   (car dics) SKK_DATADIR))))))))
    (if (not spec)
	;; merely copy without setup dictionary information.
	(copy-file "skk-setup.el.in" "skk-setup.el" 'ok-if-already-exists)
      (SKK-MK-make-setup-file spec))
    (if SKK_DICTIONARIES
	;; install dictionaries if the files exist in ./dic directory.
	(install-files SKK_DICTIONARIES DICDIR SKK_DATADIR nil t nil))
    (when (and (fboundp 'register-input-method) (not (featurep 'xemacs)))
      (copy-file "./leim-list.el.in" "./leim-list.el" 'overwrite)
      (install-elisp-modules (list 'leim-list) "." SKK_LISPDIR)
      (delete-file "./leim-list.el"))
    ;; install skk-setup.el
    (let ((dir
	   (cond ((or (boundp 'MULE)
		      (boundp 'NEMACS)
		      (not
		       (or (featurep 'xemacs)
			   (fboundp 'normal-top-level-add-subdirs-to-load-path))))
		  ;; Old Emacsen.
		  (if (member (expand-file-name ".." SKK_LISPDIR)
			      default-load-path)
		      (expand-file-name ".." SKK_LISPDIR)
		    SKK_LISPDIR))
		 (t
		  SKK_LISPDIR))))
      (install-elisp-modules (list 'skk-setup) "." dir))
    ;; install tutorials.
    (install-files SKK_TUTORIALS ETCDIR SKK_DATADIR nil t nil)
    (SKK-MK-detect-shadow-directory)))

(defun SKK-MK-detect-shadow-directory ()
  (condition-case nil
      (progn
	(require 'shadow)
	(save-match-data
	  (let ((list (find-emacs-lisp-shadows load-path))
		shadowed)
	    (while list
	      (if (and (string-match "skk-autoloads" (car list))
		       (setq list (cdr list))
		       (string-match "skk-autoloads" (car list)))
		  (setq shadowed
			(substring (file-name-directory (car list)) 0 -1)
			list nil))
	      (setq list (cdr list)))
	    (if (not shadowed)
		nil
	      (princ
	       (format "** WARNING ** %s is shadowed.  You might want to remove it\n"
		       shadowed))))))
    (error)))

(defun SKK-MK-install-info ()
  (when SKK_INFO
    (or (file-exists-p SKK_INFODIR)
	(make-directory SKK_INFODIR t))
    (SKK-MK-compile-info)
    (let ((files (list SKK_INFO))
	  (i 1) file)
      (while (file-exists-p
	      (expand-file-name (setq file (format "%s-%d" SKK_INFO i)) DOCDIR))
	(setq files (cons file files))
	(setq i (1+ i)))
      (install-files (nreverse files) DOCDIR SKK_INFODIR nil t nil))
    (require 'install-info
	     (expand-file-name "install-info.el" default-directory))
    (let ((info-file (expand-file-name SKK_INFO SKK_INFODIR))
	  (dir-file
	   (cond ((file-exists-p (expand-file-name "dir" SKK_INFODIR))
		  (expand-file-name "dir" SKK_INFODIR))
		 ((file-exists-p (expand-file-name "dir.info" SKK_INFODIR))
		  (expand-file-name "dir.info" SKK_INFODIR))
		 (t
		  (expand-file-name "dir" SKK_INFODIR)))))
      (when (file-readable-p dir-file)
	(install-info info-file dir-file nil nil 'delete))
      (install-info info-file dir-file nil nil nil))))

(defun SKK-MK-install-package ()
  (or (featurep 'xemacs) (error "This directive is only for XEmacs."))
  (let ((dics SKK_DICTIONARIES)
	delete-target exist spec)
    ;; make target directories.
    (or (file-exists-p PACKAGE_LISPDIR)
	(make-directory PACKAGE_LISPDIR t))
    (or (file-exists-p PACKAGE_DATADIR)
	(make-directory PACKAGE_DATADIR t))
    (or (file-exists-p PACKAGE_INFODIR)
	(make-directory PACKAGE_INFODIR t))
    ;; delete already installed unnecessary files.
    (setq SKK_MODULES (delq 'skk-autoloads
			    (append SKK_MODULES '(auto-autoloads custom-load))))
    (while SKK_DAREDEVIL_NOT_USE
      (setq SKK_MODULES (delq (car SKK_DAREDEVIL_NOT_USE) SKK_MODULES)
	    delete-target (expand-file-name
			   (concat (prin1-to-string (car SKK_DAREDEVIL_NOT_USE)) ".el")
			   PACKAGE_LISPDIR)
	    SKK_DAREDEVIL_NOT_USE (cdr SKK_DAREDEVIL_NOT_USE))
      (and (file-exists-p delete-target) (delete-file delete-target))
      (setq delete-target (concat delete-target "c"))
      (and (file-exists-p delete-target) (delete-file delete-target)))
    ;; install Emacs Lisp programs.
    (SKK-MK-compile-package)
    (install-elisp-modules SKK_MODULES "." PACKAGE_LISPDIR)
    (delete-file "./auto-autoloads.el")
    (delete-file "./custom-load.el")
    ;; make skk-setup.el.
    (if SKK_TUTORIALS
	(setq spec (list
		     "@TUT@"
		     (expand-file-name (car SKK_TUTORIALS) PACKAGE_DATADIR))))
    (while dics
      (when (file-exists-p (expand-file-name (car dics) DICDIR))
	(setq exist (cons (car dics) exist)))
      (setq dics (cdr dics)))
    (setq SKK_DICTIONARIES exist)
    ;; move existing largest dictionay to car of `SKK_DICTIONARIES'.
    (and (member "SKK-JISYO.M" SKK_DICTIONARIES)
	 (setq SKK_DICTIONARIES
	       (cons "SKK-JISYO.M" (delete "SKK-JISYO.M" SKK_DICTIONARIES))))
    (and (member "SKK-JISYO.L" SKK_DICTIONARIES)
	 (setq SKK_DICTIONARIES
	       (cons "SKK-JISYO.L" (delete "SKK-JISYO.L" SKK_DICTIONARIES))))
    (if SKK_DICTIONARIES
	(progn
	  (setq spec
		(append spec
			(list "@AUXDIC@"
			    (expand-file-name
			     (car SKK_DICTIONARIES) PACKAGE_DATADIR))))
	  (if SKK_SET_JISYO
	      (setq spec
		    (nconc spec
			   (list
			    "@DIC@"
			    (expand-file-name (car SKK_DICTIONARIES) PACKAGE_DATADIR)))))
	  ;; install dictionaries if the files exist in ./dic directory.
	  (install-files SKK_DICTIONARIES DICDIR PACKAGE_DATADIR nil t nil))
      ;; when dictionaries do not exist in ./dic subdirectory, check
      ;; already installed dictionary and detect largest one to setup
      ;; skk-setup.el.in.
      (setq dics '("SKK-JISYO.L" "SKK-JISYO.M" "SKK-JISYO.S"))
      (while (and dics
		  (not
		   (or
		    (file-exists-p (expand-file-name (car dics) PACKAGE_DATADIR))
		    (file-exists-p (expand-file-name (car dics) SKK_DATADIR)))))
	(setq dics (cdr dics)))
      (if dics
	  (let ((dic
		 (if (file-exists-p (expand-file-name (car dics) PACKAGE_DATADIR))
		     (expand-file-name (car dics) PACKAGE_DATADIR)
		   (expand-file-name (car dics) SKK_DATADIR))))
	    (setq spec (nconc spec (list "@AUXDIC@" dic)))
	    (if SKK_SET_JISYO
		(setq spec (nconc spec (list "@DIC@" dic)))))))
    (if (not spec)
	;; merely copy without setup dictionary information.
	(copy-file "skk-setup.el.in" "skk-setup.el" 'ok-if-already-exists)
      (SKK-MK-make-setup-file spec))
    ;; install skk-setup.el
    (install-elisp-modules (list 'skk-setup) "." PACKAGE_LISPDIR)
    ;; install infos.
    (SKK-MK-compile-info)
    (when SKK_INFO
      (let ((files (list SKK_INFO))
	    (i 1) file)
	(while (file-exists-p
		(expand-file-name (setq file (format "%s-%d" SKK_INFO i)) DOCDIR))
	  (setq files (cons file files))
	  (setq i (1+ i)))
	(install-files (nreverse files) DOCDIR PACKAGE_INFODIR nil t nil)))
    ;; install tutorials.
    (install-files SKK_TUTORIALS ETCDIR PACKAGE_DATADIR nil t nil)
    (SKK-MK-detect-shadow-directory)))

(defun SKK-MK-texinfo-format (targets)
  (let (
	;; Emacs20.2's default is 'raw-text-unix.
	(coding-system-for-write SKK-MK-texinfo-coding-system)
	x obuf beg standard-output)
    (require 'ptexinfmt (expand-file-name "ptexinfmt.el" default-directory))
    (while targets
      (setq x (expand-file-name (car targets) DOCDIR))
      (find-file x)
      (setq obuf (current-buffer))
      (texinfo-format-buffer)
      (save-buffer)
      (kill-buffer (current-buffer))	; info
      (kill-buffer obuf)		; texi
      (setq targets (cdr targets)))))

(defun SKK-MK-what-where ()
  (interactive)
  (let ((string
	 (format "
SKK modules:
  %s
  -> %s

SKK infos:
  %s
  -> %s

SKK tutorials:
  %s
  -> %s
"
		 (mapconcat 'symbol-name SKK_MODULES ", ")
		 SKK_LISPDIR
		 SKK_INFO
		 SKK_INFODIR
		 (mapconcat 'identity SKK_TUTORIALS ", ")
		 SKK_DATADIR)))
    (if (interactive-p)
	(progn (with-output-to-temp-buffer "*What where*" (princ string))
	       (message ""))
      (princ string))))

(defun SKK-MK-what-where-package ()
  (interactive)
  (or (featurep 'xemacs) (error "This directive is only for XEmacs."))
  (let ((string
	 (format "
SKK modules:
  %s
  -> %s

SKK infos:
  %s
  -> %s

SKK tutorials:
  %s
  -> %s
"
		 (mapconcat 'symbol-name (delq 'skk-autoloads SKK_MODULES)
			    ", ")
		 PACKAGE_LISPDIR
		 SKK_INFO
		 PACKAGE_INFODIR
		 (mapconcat 'identity SKK_TUTORIALS ", ")
		 PACKAGE_DATADIR)))
    (if (interactive-p)
	(progn (with-output-to-temp-buffer "*What where*" (princ string))
	       (message ""))
      (princ string))))

(defun SKK-MK-generate-autoloads-el ()
  "Generate skk-autoload.el."
  (let ((modules SKK_MODULES)
	(buf (get-buffer-create " *SKK-MK-generate-autoloads-el*"))
	(sort-min)
	(funcs)
	standard-output)
    (save-excursion
      (set-buffer buf)
      (erase-buffer)
      (insert "\
;;; skk-autoloads.el --- autoload settings for SKK.

;; This file was generated automatically by SKK-MK at "
	      (current-time-string)
	      ".

;; This file is part of Daredevil SKK.

;; Daredevil SKK 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 versions 2, or (at your option)
;; any later version.

;; Daredevil SKK 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 Daredevil SKK, see the file COPYING.  If not, write to the Free
;; Software Foundation Inc., 59 Temple Place - Suite 330, Boston,
;; MA 02111-1307, USA.

;;; Code:\n\n")
      (cond
       ((and (condition-case nil
		 (and (require 'autoload)
		      (require 'poem))
	       (error))
	     (fboundp 'generate-file-autoloads))
	(while modules
	  (let ((file (expand-file-name
		       (format "%s.el" (car modules)) default-directory)))
	    (and (file-exists-p file)
		 (generate-file-autoloads file)))
	  (setq modules (cdr modules)))
	(goto-char (point-max))
	(insert "\n(provide 'skk-autoloads)\n;;; skk-autoloads.el ends here\n")
	(write-region-as-coding-system
	 (if (boundp 'MULE) *junet*unix 'iso-2022-jp)
	 (point-min) (point-max) "skk-autoloads.el" nil 'quiet)
	(kill-buffer buf))
       (t
	(setq sort-min (point))
	(while modules
	  (setq funcs (SKK-MK-collect-autoload-functions (car modules)))
	  (while funcs
	    (insert "(autoload '" (caar funcs)
		    " \"" (file-name-nondirectory (symbol-name (car modules)))
		    "\" nil "
		    (symbol-name (if (cdar funcs) t))
		    " nil)\n")
	    (setq funcs (cdr funcs)))
	  (setq modules (cdr modules)))
	(sort-lines nil sort-min (point-max))
	(goto-char (point-max))
	(insert "\n(provide 'skk-autoloads)\n;;; skk-autoloads.el ends here\n")
	(write-region (point-min) (point-max) "skk-autoloads.el" nil 'quiet)
	(kill-buffer buf))))))

(defun SKK-MK-generate-autoloads-el-package ()
  "Generate auto-autoload.el."
  (let ((modules SKK_MODULES)
	(buf (get-buffer-create " *SKK-MK-generate-autoloads-el*")))
    (require 'poem)
    (save-excursion
      (set-buffer buf)
      (erase-buffer)
      (dolist (module modules)
	(let ((file (expand-file-name (format "%s.el" module) default-directory)))
	  (and (file-exists-p file)
	       (generate-file-autoloads file))))
      (eval-current-buffer)
      (let ((generated-autoload-file
	     (expand-file-name "auto-autoloads.el" default-directory)))
	(setq buffer-file-name generated-autoload-file)
	(fixup-autoload-buffer "skk-autoloads")
	(goto-char (point-max))
	(unless (bolp)
	  (insert "\n"))
	(insert "\

;;;***
\014
;;; Load \"skk-setup.el\".

(when site-start-file
  (require 'skk-setup))
")
	(write-region-as-coding-system
	 'iso-2022-jp
	 (point-min) (point-max) generated-autoload-file)
	(kill-buffer buf)
	(add-to-list 'command-line-args-left ".")
	(Custom-make-dependencies)))))

(defun SKK-MK-collect-autoload-functions (module)
  "Return a list of autoload functions defined in MODULE."
  (let ((el-file (concat (symbol-name module) ".el"))
        (funcs))
    (if (file-exists-p el-file)
        (progn
          (save-excursion
            (insert-file-contents el-file)
            (while (re-search-forward "^;;;###autoload" nil t)
              (beginning-of-line 2)
              (if (looking-at "(defun[ 	]+\\([^ 	(]+\\)")
                  (setq funcs
                        (cons (cons (match-string 1)
                                    (save-excursion
                                      (re-search-forward
                                       "^[ 	]*(interactive"
                                       (save-excursion
					 (re-search-forward "^(defun" nil t 2))
                                       t)))
                              funcs)))))
          (delete-region (point) (point-max))))
    funcs))

;;; SKK-MK ends here
