diff lisp/find-paths.el @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children abe6d1db359e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/find-paths.el	Mon Aug 13 11:28:15 2007 +0200
@@ -0,0 +1,302 @@
+;;; find-paths.el --- setup various XEmacs paths
+
+;; Copyright (C) 1985-1986, 1990, 1992-1997 Free Software Foundation, Inc.
+;; Copyright (c) 1993, 1994 Sun Microsystems, Inc.
+;; Copyright (C) 1995 Board of Trustees, University of Illinois
+
+;; Author: Mike Sperber <sperber@informatik.uni-tuebingen.de>
+;; Maintainer: XEmacs Development Team
+;; Keywords: internal, dumped
+
+;; This file is part of XEmacs.
+
+;; XEmacs 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, or (at your option)
+;; any later version.
+
+;; XEmacs 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 XEmacs; see the file COPYING.  If not, write to the 
+;; Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Synched up with: Not in FSF.
+
+;;; Commentary:
+
+;; This file is dumped with XEmacs.
+
+;; This file contains the library functionality to find paths into the
+;; XEmacs hierarchy.
+
+;;; Code:
+
+(defvar paths-version-control-filename-regexp
+  "^\\(RCS\\|CVS\\|SCCS\\)$"
+  "File bases associated with version control.")
+
+(defvar paths-lisp-filename-regexp
+  "^\\(.*\\.elc?\\)$"
+  "File bases that contain Lisp file.")
+
+(defvar paths-no-lisp-directory-regexp
+  (concat "\\(" paths-version-control-filename-regexp "\\)"
+	  "\\|"
+	  "\\(" paths-lisp-filename-regexp "\\)")
+  "File bases that may not be directories containing Lisp code.")
+
+(defun paths-find-recursive-path (directories &optional max-depth exclude-regexp)
+  "Return a list of the directory hierarchy underneath DIRECTORIES.
+The returned list is sorted by pre-order and lexicographically.
+MAX-DEPTH limits the depth of the search to MAX-DEPTH level,
+if it is a number.  If MAX-DEPTH is NIL, the search depth is unlimited.
+EXCLUDE-REGEXP is a regexp that matches directory names to exclude
+from the search."
+  (let ((path '()))
+    (while directories
+      (let ((directory (file-name-as-directory
+			(expand-file-name
+			 (car directories)))))
+	(if (paths-file-readable-directory-p directory)
+	    (let ((raw-entries
+		   (if (equal 0 max-depth)
+		       '()
+		     (directory-files directory nil "^[^.-]")))
+		  (reverse-dirs '()))
+	      (while raw-entries
+		(if (null (string-match exclude-regexp (car raw-entries)))
+		    (setq reverse-dirs
+			  (cons (expand-file-name (car raw-entries) directory)
+				reverse-dirs)))
+		(setq raw-entries (cdr raw-entries)))
+
+	      (let ((sub-path
+		     (paths-find-recursive-path (reverse reverse-dirs)
+						(if (numberp max-depth)
+						    (- max-depth 1)
+						  max-depth)
+						exclude-regexp)))
+		(setq path (nconc path
+				  (list directory)
+				  sub-path))))))
+      (setq directories (cdr directories)))
+    path))
+
+(defun paths-file-readable-directory-p (filename)
+  "Check if filename is a readable directory."
+  (and (file-directory-p filename)
+       (file-readable-p filename)))
+
+(defun paths-find-recursive-load-path (directories &optional max-depth)
+  "Construct a recursive load path underneath DIRECTORIES."
+  (paths-find-recursive-path directories
+			     max-depth paths-no-lisp-directory-regexp))
+
+(defun paths-emacs-root-p (directory)
+  "Check if DIRECTORY is a plausible installation root for XEmacs."
+  (or
+   ;; installed
+   (paths-file-readable-directory-p (paths-construct-path (list directory
+								"lib"
+								emacs-program-name)))
+   ;; in-place or windows-nt
+   (and
+    (paths-file-readable-directory-p (paths-construct-path (list directory "lisp")))
+    (paths-file-readable-directory-p (paths-construct-path (list directory "etc"))))))
+
+(defun paths-chase-symlink (file-name)
+  "Chase a symlink until the bitter end."
+      (let ((maybe-symlink (file-symlink-p file-name)))
+	(if maybe-symlink
+	    (let* ((directory (file-name-directory file-name))
+		   (destination (expand-file-name maybe-symlink directory)))
+	      (paths-chase-symlink destination))
+	  file-name)))
+
+(defun paths-find-emacs-root
+  (invocation-directory invocation-name)
+  "Find the run-time root of XEmacs."
+  (let* ((executable-file-name (paths-chase-symlink
+				(concat invocation-directory
+					invocation-name)))
+	 (executable-directory (file-name-directory executable-file-name))
+	 (maybe-root-1 (file-name-as-directory
+			(paths-construct-path '("..") executable-directory)))
+	 (maybe-root-2 (file-name-as-directory
+			(paths-construct-path '(".." "..") executable-directory))))
+    (or (and (paths-emacs-root-p maybe-root-1)
+	     maybe-root-1)
+	(and (paths-emacs-root-p maybe-root-2)
+	     maybe-root-2))))
+
+(defun paths-construct-path (components &optional expand-directory)
+  "Convert list of path components COMPONENTS into a path.
+If EXPAND-DIRECTORY is non-NIL, use it as a directory to feed
+to EXPAND-FILE-NAME."
+  (let* ((reverse-components (reverse components))
+	 (last-component (car reverse-components))
+	 (first-components (reverse (cdr reverse-components)))
+	 (path
+	  (apply #'concat
+		 (append (mapcar #'file-name-as-directory first-components)
+			 (list last-component)))))
+    (if expand-directory
+	(expand-file-name path expand-directory)
+      path)))
+
+(defun paths-construct-emacs-directory (root suffix base)
+  "Construct a directory name within the XEmacs hierarchy."
+  (file-name-as-directory
+   (expand-file-name
+    (concat
+     (file-name-as-directory root)
+     suffix
+     base))))
+
+(defun paths-find-emacs-directory (roots suffix base
+				   &optional envvar default keep-suffix)
+  "Find a directory in the XEmacs hierarchy.
+ROOTS must be a list of installation roots.
+SUFFIX is the subdirectory from there.
+BASE is the base to look for.
+ENVVAR is the name of the environment variable that might also
+specify the directory.
+DEFAULT is the preferred value.
+If KEEP-SUFFIX is non-nil, the suffix must be respected in searching
+the directory."
+  (let ((preferred-value (or (and envvar (getenv envvar))
+			     default)))
+    (if (and preferred-value
+	     (paths-file-readable-directory-p preferred-value))
+	(file-name-as-directory preferred-value)
+      (catch 'gotcha
+	(while roots
+	  (let* ((root (car roots))
+		 ;; installed
+		 (path (paths-construct-emacs-directory root suffix base)))
+	    (if (paths-file-readable-directory-p path)
+		(throw 'gotcha path)
+	      ;; in-place
+	      (if (null keep-suffix)
+		  (let ((path (paths-construct-emacs-directory root "" base)))
+		    (if (paths-file-readable-directory-p path)
+			(throw 'gotcha path))))))
+	  (setq roots (cdr roots)))
+	nil))))
+
+(defun paths-find-site-directory (roots base &optional envvar default)
+  "Find a site-specific directory in the XEmacs hierarchy."
+  (paths-find-emacs-directory roots
+			      (file-name-as-directory
+			       (paths-construct-path (list
+						      "lib"
+						      emacs-program-name)))
+			      base
+			      envvar default))
+
+(defun paths-find-version-directory (roots base
+				     &optional envvar default enforce-version)
+  "Find a version-specific directory in the XEmacs hierarchy.
+If ENFORCE-VERSION is non-nil, the directory must contain the XEmacs version."
+  (paths-find-emacs-directory roots
+			      (file-name-as-directory
+			       (paths-construct-path
+				(list "lib"
+				      (construct-emacs-version-name))))
+			      base
+			      envvar default
+			      enforce-version))
+
+(defun paths-find-architecture-directory (roots base &optional envvar default)
+  "Find an architecture-specific directory in the XEmacs hierarchy."
+  (or
+   ;; from more to less specific
+   (paths-find-version-directory roots
+				 (concat base system-configuration)
+				 envvar default)
+   (paths-find-version-directory roots
+				 base
+				 envvar)
+   (paths-find-version-directory roots
+				 system-configuration
+				 envvar)))
+
+(defun construct-emacs-version-name ()
+  "Construct the raw XEmacs version number."
+  (concat emacs-program-name "-" emacs-program-version))
+
+(defun paths-directories-which-exist (directories)
+  "Return the directories among DIRECTORIES."
+  (let ((reverse-directories '()))
+    (while directories
+      (if (paths-file-readable-directory-p (car directories))
+	  (setq reverse-directories
+		(cons (car directories)
+		      reverse-directories)))
+      (setq directories (cdr directories)))
+    (reverse reverse-directories)))
+
+(defun paths-uniq-append (list-1 list-2)
+  "Append LIST-1 and LIST-2, omitting duplicates."
+  (let ((reverse-survivors '()))
+    (while list-2
+      (if (null (member (car list-2) list-1))
+	  (setq reverse-survivors (cons (car list-2) reverse-survivors)))
+      (setq list-2 (cdr list-2)))
+    (append list-1
+	    (reverse reverse-survivors))))
+
+(defun paths-filter (predicate list)
+  "Delete all matches of PREDICATE from LIST."
+  (let ((reverse-result '()))
+    (while list
+      (if (funcall predicate (car list))
+	  (setq reverse-result (cons (car list) reverse-result)))
+      (setq list (cdr list)))
+    (nreverse reverse-result)))
+
+(defun paths-decode-directory-path (string &optional drop-empties)
+  "Split STRING at path separators into a directory list.
+Non-\"\" comonents are converted into directory form.
+If DROP-EMPTIES is non-NIL, \"\" components are dropped from the output.
+Otherwise, they are left alone."
+  (let* ((components (split-path string))
+	 (directories
+	  (mapcar #'(lambda (component)
+		      (if (string-equal "" component)
+			  component
+			(file-name-as-directory component)))
+		  components)))
+    (if drop-empties
+	(paths-filter #'(lambda (component)
+			  (null (string-equal "" component)))
+		      directories)
+      directories)))
+
+(defun paths-find-emacs-roots (invocation-directory
+			       invocation-name)
+  "Find all plausible installation roots for XEmacs."
+  (let* ((potential-invocation-root
+	  (paths-find-emacs-root invocation-directory invocation-name))
+	 (invocation-roots
+	  (and potential-invocation-root
+	       (list potential-invocation-root)))
+	 (potential-installation-roots
+	  (paths-uniq-append
+	   (and configure-exec-prefix-directory
+		(list (file-name-as-directory
+		       configure-exec-prefix-directory)))
+	   (and configure-prefix-directory
+		(list (file-name-as-directory
+		       configure-prefix-directory)))))
+	 (installation-roots
+	  (paths-filter #'paths-emacs-root-p potential-installation-roots)))
+    (paths-uniq-append invocation-roots
+		       installation-roots)))
+
+;;; find-paths.el ends here