[comp.emacs] zapping those nasty multiple defs

merlyn@intelob.intel.com (Randal L. Schwartz @ Stonehenge) (09/21/88)

Elisp suffers from having to have names for all static objects come
from one global array.  Have you ever wondered just how successful
we've been at avoiding having two different elisp packages define the
same entries with different meanings?  Well, I did.  The attached code
scans through the lisp and src directories, finding all possible
well-behaved insertions into `obarray', and gives a
file-and-line-number cross reference for each.  Functions and
variables are considered separately.

Why is this being posted in gnu.emacs.bug?  Well, after running this
over the 18.50 version, I found some collisions (a few were removed in
the 18.51 and 18.52 versions, to which I no longer have immediate
access, so I'm not publishing the definitive list).  My request is
that the powers-that-be run this code before releasing 19.xx (or
18.53) and remove the collisions.

For example: `abs' is defined in mim-mode.el, float.el, and cl.el.  I
very much doubt that the defs in float and cl are compatible.
Similarly, `beginning-of-window' is defined in both mlsupport.el and
edt.el, `caar' in mh-e.el and cl.el, `caddr' in both doctor.el (!) and
cl.el, `cadr' and `cddr' in mh-e.el, doctor.el, and cl.el,
`delete-previous-word' in mlsupport.el and edt.el,
`line-to-top-of-window' in no less than four places, `lisp-send-defun'
in both shell.el and lisp-mode.el, `member' in both doctor.el and
cl.el, `mod' in subr.el and cl.el, `setq-default' in data.c and
mlsupport.el (hence the need for scanning the C files), `when' in
mh-e.el and cl.el.  This is not an exaustive list, nor do I have
access to 18.52 for the latest test.

Caveats:

* Code presumes lisp and src directories are siblings of the "exec-directory".

* A few collisions are not really.  `loaddefs.el' has a lot of setting that
  gets duplicated in the real files, and some of the C files have duplicate
  definitions in order to make the DOC file.  #ifdef's are also ignored.

* Code presumes well-formatted C and Elisp files.  See the regexps for
  details.

Enjoy.  Comments on my coding style should be sent by mail, please.

--- CUT HERE --- (signature is at the end, after the other cut) ---
(with-output-to-temp-buffer "*result*"
  (let ((ob (make-vector 997 0))
	(symlist nil))
    (mapcar
     '(lambda (fn)
	(message "Seeing %s..." fn)
	(set-buffer (generate-new-buffer " tmp"))
	(unwind-protect
	    (progn
	      (insert-file-contents fn)
	      (setq fn (file-name-nondirectory fn)
		    case-fold-search nil)
	      (emacs-lisp-mode)
	      (while (re-search-forward
		      (if (string= ".el" (substring fn -3))
			  "^(\\(defun\\s +\\|defmacro\\s +\\|fset\\s +'\\s *\\)"
			"^\\s *\\(DEFUN\\|DEFSIMPLE\\|DEFPRED\\)\\s +(\"")
		      nil t)
		(let ((sym (intern (buffer-substring
				    (prog1 (point)
				      (forward-sexp 1))
				    (point))
				   ob)))
		  ;; (message "function %s in %s..." sym fn)
		  (fset sym (cons (format "%s:%d"
					  fn
					  (count-lines (point-min) (point)))
				  (and (fboundp sym)
				       (symbol-function sym))))))
	      (goto-char (point-min))
	      (while (re-search-forward
		      (if (string= ".el" (substring fn -3))
			  "^(\\(defconst\\s +\\|defvar\\s +\\|setq\\s +\\|set\\s +'\\s *\\)"
			"^\\s *DEFVAR[A-Z_]*\\s +(\"")
		      nil t)
		(let ((sym (intern (buffer-substring
				    (prog1 (point)
				      (forward-sexp 1))
				    (point))
				   ob)))
		  ;; (message "variable %s in %s..." sym fn)
		  (set sym (cons (format "%s:%d"
					 fn
					 (count-lines (point-min) (point)))
				 (and (boundp sym)
				      (symbol-value sym)))))))
	  (kill-buffer (current-buffer))))
     (append
      (directory-files (concat exec-directory "../lisp/") t "\\.el$")
      (directory-files (concat exec-directory "../src/") t "\\.c$")))
    (mapatoms
     '(lambda (sym)
	(setq symlist (cons sym symlist)))
     ob)
    (setq symlist (sort symlist 'string<))
    (mapcar
     '(lambda (sym)
	(princ (concat
		(symbol-name sym) ":\n"
		(if (fboundp sym)
		    (concat " F: "
			    (mapconcat 'identity (symbol-function sym) " ")
			    "\n")
		  "")
		(if (boundp sym)
		    (concat " V: "
			    (mapconcat 'identity (symbol-value sym) " ")
			    "\n")
		  "")
		"\n")))
     symlist)))
--- CUT HERE ---
-- 
Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095
on contract to BiiN Technical Information Services (for now :-),
in a former Intel building in Hillsboro, Oregon, USA
<merlyn@intelob.intel.com> or ...!tektronix!inteloa[!intelob]!merlyn
Standard disclaimer: I *am* my employer!