unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
@ 2006-05-10 21:11 Alan Mackenzie
  2006-05-11 16:46 ` Stuart D. Herring
  2006-05-14 11:07 ` FIXED!! " Alan Mackenzie
  0 siblings, 2 replies; 14+ messages in thread
From: Alan Mackenzie @ 2006-05-10 21:11 UTC (permalink / raw)


Hi, Emacs!

The doc string (and manual entry) for eval-after-load are a bit hazy and
indefinite.  Here is the doc-string:

   "Arrange that, if FILE is ever loaded, FORM will be run at that time.
    This makes or adds to an entry on `after-load-alist'.
    If FILE is already loaded, evaluate FORM right now.
    It does nothing if FORM is already on the list for FILE.
    FILE must match exactly.  Normally FILE is the name of a library,
    with no directory or extension specified, since that is how `load'
    is normally called.
    FILE can also be a feature (i.e. a symbol), in which case FORM is
    evaluated whenever that feature is `provide'd."

Some problems are:
(i) "FILE must match exactly" doesn't say what FILE must match, or how it
must match it, and it is unclear what "exactly" means.  Given this
description, I would not expect the argument "font-lock" to match the
file name "font-lock.elc", but it does.  :-(

(ii) The doc-string doesn't say what happens when FILE gets loaded again.


I propose the following as a replacement:

   "Arrange that, if FILE is ever loaded, FORM will be run at that time.
    If FILE is already loaded, evaluate FORM right now.

    FILE, a string, must be either an absolute file name or a file name with
    no directory part; in either case it may have an extension
    \(e.g. \".el\") or may lack one.  Symbolic links in an absolute file name
    will be chased out before it is matched against the names of loaded files.

    When FILE is absolute, only FILE in that directory triggers evaluation
    of FORM, otherwise FILE in any directory will do.  If FILE has an
    extension, only a file with that exact extension will trigger evaluation,
    otherwise any extension will do it.

    Alternatively, FILE can be a feature (i.e. a symbol), in which case FORM
    is evaluated whenever that feature is `provide'd.

    Usually FILE is just a library name like \"font-lock\".

    If a matching file is loaded again, FORM will be evaluated again.

    This makes or adds to an entry on `after-load-alist'.
    It does nothing if FORM is already on the list for FILE."

Naturally, the code will need tweaking a bit to fit this doc-string.

What do you think?

-- 
Alan.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
  2006-05-10 21:11 Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history] Alan Mackenzie
@ 2006-05-11 16:46 ` Stuart D. Herring
  2006-05-11 17:19   ` Alan Mackenzie
  2006-05-14 11:07 ` FIXED!! " Alan Mackenzie
  1 sibling, 1 reply; 14+ messages in thread
From: Stuart D. Herring @ 2006-05-11 16:46 UTC (permalink / raw)
  Cc: emacs-devel

> (i) "FILE must match exactly" doesn't say what FILE must match, or how it
> must match it, and it is unclear what "exactly" means.  Given this
> description, I would not expect the argument "font-lock" to match the
> file name "font-lock.elc", but it does.  :-(

This may be a horribly naive question, but why doesn't this mechanism just
use the `provide'd symbols?  Is there really much need to use
`eval-after-load' with libraries that are considered so basic (i.e.,
automatically loaded) that they don't provide anything?  I would think
that things like `emacs-startup-hook' would be sufficient for that.

It just seems eminently clear to me what
(eval-after-provide 'dired (unload-feature 'dired))
intends to do, and how to define it precisely.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
  2006-05-11 16:46 ` Stuart D. Herring
@ 2006-05-11 17:19   ` Alan Mackenzie
  2006-05-11 17:46     ` Stuart D. Herring
  0 siblings, 1 reply; 14+ messages in thread
From: Alan Mackenzie @ 2006-05-11 17:19 UTC (permalink / raw)
  Cc: emacs-devel

Hi, Stuart!

On Thu, 11 May 2006, Stuart D. Herring wrote:

>> (i) "FILE must match exactly" doesn't say what FILE must match, or how it
>> must match it, and it is unclear what "exactly" means.  Given this
>> description, I would not expect the argument "font-lock" to match the
>> file name "font-lock.elc", but it does.  :-(

>This may be a horribly naive question, but why doesn't this mechanism just
>use the `provide'd symbols?  Is there really much need to use
>`eval-after-load' with libraries that are considered so basic (i.e.,
>automatically loaded) that they don't provide anything?  I would think
>that things like `emacs-startup-hook' would be sufficient for that.

The use of symbols (as opposed to file names) here has only just been
introduced into Emacs (sometime in Emacs 22), so there are many millions
of (eval-after-load "foo" ....) forms in existing source throughout the
Emacs universe.  We need to stay compatible with that source.

>It just seems eminently clear to me what (eval-after-provide 'dired
>(unload-feature 'dired)) intends to do, and how to define it precisely.

IWHBB, probably, if it had been done this way back in 4004 B.C.  Maybe we
can phase out the (eval-after-load "foo" ....) variant by Emacs 24 or so.
Maybe, on the other hand, there are users who "need" the flexibility of
specifying an exact file name.

>Davis

-- 
Alan.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
  2006-05-11 17:19   ` Alan Mackenzie
@ 2006-05-11 17:46     ` Stuart D. Herring
  2006-05-11 21:44       ` Alan Mackenzie
  2006-05-12  4:15       ` Richard Stallman
  0 siblings, 2 replies; 14+ messages in thread
From: Stuart D. Herring @ 2006-05-11 17:46 UTC (permalink / raw)
  Cc: emacs-devel

> The use of symbols (as opposed to file names) here has only just been
> introduced into Emacs (sometime in Emacs 22), so there are many millions
> of (eval-after-load "foo" ....) forms in existing source throughout the
> Emacs universe.  We need to stay compatible with that source.

Yes, I realize that.  I was just being dumb and talking before reading; I
see now that exactly what I was suggesting is already implemented in
parallel with the filename system.  It seems to me that the simple way to
handle the real problem (rather than the one I fabricated) is to
fully-canonicalize (find real file name, find absolute file name, chase
symlinks) the arguments to both `eval-after-load' and `load' and compare
them (that is, use them to read/write the alist) afterwards.  But could
there be a problem where preloaded files didn't match on a different
machine?  If so, it might make sense to express the file names relative to
the entry of `load-path' that let them be found.  Of course, then you
couldn't chase symlinks.  Maybe during preloading `load-history' should
get the short names (e.g., "font-lock", "simple") of loaded files, and
then at real startup do the canonicalization before loading anything that
would need to use `eval-after-load'?  Since it'd only be preloaded files,
customizations to `load-path' would probably be irrelevant, so it would be
okay to resolve them before loading .emacs.

Apologies if this is uneducated rambling; I'm not too familiar with this
feature.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
  2006-05-11 17:46     ` Stuart D. Herring
@ 2006-05-11 21:44       ` Alan Mackenzie
  2006-05-12  4:15       ` Richard Stallman
  1 sibling, 0 replies; 14+ messages in thread
From: Alan Mackenzie @ 2006-05-11 21:44 UTC (permalink / raw)
  Cc: emacs-devel

Evening, Stuart!

On Thu, 11 May 2006, Stuart D. Herring wrote:

>> The use of symbols (as opposed to file names) here has only just been
>> introduced into Emacs (sometime in Emacs 22), so there are many millions
>> of (eval-after-load "foo" ....) forms in existing source throughout the
>> Emacs universe.  We need to stay compatible with that source.

>Yes, I realize that.  I was just being dumb and talking before reading;
>I see now that exactly what I was suggesting is already implemented in
>parallel with the filename system.

>It seems to me that the simple way to handle the real problem (rather
>than the one I fabricated) is to fully-canonicalize (find real file
>name, find absolute file name, chase symlinks) the arguments to both
>`eval-after-load' and `load' and compare them (that is, use them to
>read/write the alist) afterwards.

I proposed a patch (for load) to do this yesterday.

>But could there be a problem where preloaded files didn't match on a
>different machine?  If so, it might make sense to express the file names
>relative to the entry of `load-path' that let them be found.

This is, in fact done.  The preloaded files are expressed relative to
..../emacs/lisp, and fleshed out to absolute names when Emacs is started.
After all, the preloaded files are loaded from the building lisp
directory, which is rarely the same as the one Emacs is installed to.

>Of course, then you couldn't chase symlinks.  Maybe during preloading
>`load-history' should get the short names (e.g., "font-lock", "simple")
>of loaded files, and then at real startup do the canonicalization before
>loading anything that would need to use `eval-after-load'?

Have a look at command-line (in startup.el) and Fload (in lread.c).  They
work almost exactly like you suggest they should.  :-)

>Since it'd only be preloaded files, customizations to `load-path' would
>probably be irrelevant, so it would be okay to resolve them before
>loading .emacs.

Indeed.

>Apologies if this is uneducated rambling; I'm not too familiar with this
>feature.

Not at all, great minds think alike.  :-)  Happy hacking!

>Davis

-- 
Alan.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
  2006-05-11 17:46     ` Stuart D. Herring
  2006-05-11 21:44       ` Alan Mackenzie
@ 2006-05-12  4:15       ` Richard Stallman
  1 sibling, 0 replies; 14+ messages in thread
From: Richard Stallman @ 2006-05-12  4:15 UTC (permalink / raw)
  Cc: acm, emacs-devel

      Maybe during preloading `load-history' should
    get the short names (e.g., "font-lock", "simple") of loaded files, and
    then at real startup do the canonicalization before loading anything that
    would need to use `eval-after-load'?

That is what already happens.  See line 645 in startup.el.

That being so, is it obvious how to fix this bug?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* FIXED!! Re: Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
  2006-05-10 21:11 Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history] Alan Mackenzie
  2006-05-11 16:46 ` Stuart D. Herring
@ 2006-05-14 11:07 ` Alan Mackenzie
  2006-05-15  5:13   ` Richard Stallman
  1 sibling, 1 reply; 14+ messages in thread
From: Alan Mackenzie @ 2006-05-14 11:07 UTC (permalink / raw)
  Cc: Richard Stallman

Hi, again, Emacs!

On Wed, 10 May 2006, Alan Mackenzie wrote:

>Hi, Emacs!

>The doc string (and manual entry) for eval-after-load are a bit hazy and
>indefinite.  Here is the doc-string:

>   "Arrange that, if FILE is ever loaded, FORM will be run at that time.
>    This makes or adds to an entry on `after-load-alist'.
>    If FILE is already loaded, evaluate FORM right now.
>    It does nothing if FORM is already on the list for FILE.
>    FILE must match exactly.  Normally FILE is the name of a library,
>    with no directory or extension specified, since that is how `load'
>    is normally called.
>    FILE can also be a feature (i.e. a symbol), in which case FORM is
>    evaluated whenever that feature is `provide'd."

>Some problems are:
>(i) "FILE must match exactly" doesn't say what FILE must match, or how it
>must match it, and it is unclear what "exactly" means.  Given this
>description, I would not expect the argument "font-lock" to match the
>file name "font-lock.elc", but it does.  :-(

>(ii) The doc-string doesn't say what happens when FILE gets loaded again.

Combining this with these OTHER PROBLEMS (already posted on emacs-devel):

> I do: emacs-22.0.50.1 -Q
>       M-x load-file <ret> ~acm/emacs/emacs/lisp/progmodes/cc-mode.elc
>       C-h v load-history.
>
> Then:
>       M-: (eval-after-load "cc-mode" '(beep))  fails.
>       M-: (eval-after-load "cc-fonts" '(beep))  beeps.
>       M-: (eval-after-load "english" '(beep))  fails.
>
> Here are these file names as they appear in load-history:
>
> 1. "/home/acm/emacs/emacs/lisp/progmodes/cc-mode.elc"
> 2. "/mnt/hda7/emacs/lisp/progmodes/cc-fonts.elc"
> 3. "/mnt/hda7/emacs/lisp/language/english.elc"
>
> 1 and 2 are incompatible.  3 is plain wrong - the actual file is
> english.el (english.elc doesn't exist; you can't compile english).

and

> Start Emacs 22 with -Q, then visit a file.c.
>
> Emacs displays the message:
>
>   File mode specification error: (void-variable c-font-lock-keywords-3)

#########################################################################

The following patch, though large, fixes all of these problems, thusly:

1. The file name recorded in load-history is the absolute true file name
of the file actually loaded.  The way this is done for preloaded files
has been simplified.

2. (eval-after-load FILE ...) now triggers on ANY file which matches
FILE, not just the one (if any) found in load-path.

3. (eval-after-load "foo" ...), for example will trigger on "..../foo",
"..../foo.el",  "..../foo.elc", or even "..../foo.el.gz".

[Incidentally, it needs BASE_PURESIZE to be increased.]



2006-05-14  Alan Mackenzie  <acm@muc.de>

	* startup.el (command-line): For names of preloaded files, don't
	append ".elc" (now done in Fload), and call file-truename on the
	lisp directory.

	* international/mule.el (load-with-code-conversion): Do the
	eval-after-load stuff by calling do-after-load-evaluation.

	* subr.el (eval-after-load): Fix the doc-string.  Allow FILE to
	match ANY loaded file with the right name, not just those in
	load-path.

	* subr.el: New functions load-history-regexp,
	load-history-filename-element, loaded-filename,
	get-after-load-alist-matches, do-after-load-evaluation.

	* loadup.el: load emacs-lisp/regexp-opt at preload time to support
	Fload.


Index: lisp/startup.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/startup.el,v
retrieving revision 1.407
diff -c -r1.407 startup.el
*** lisp/startup.el	5 May 2006 14:05:54 -0000	1.407
--- lisp/startup.el	14 May 2006 09:51:50 -0000
***************
*** 644,661 ****
  
    ;; Convert preloaded file names to absolute.
    (let ((lisp-dir
! 	 (file-name-directory
! 	  (locate-file "simple" load-path
! 		       (get-load-suffixes)))))
  
      (setq load-history
  	  (mapcar (lambda (elt)
  		    (if (and (stringp (car elt))
  			     (not (file-name-absolute-p (car elt))))
  			(cons (concat lisp-dir
! 				      (car elt)
! 				      (if (string-match "[.]el$" (car elt))
! 					  "" ".elc"))
  			      (cdr elt))
  		      elt))
  		  load-history)))
--- 644,660 ----
  
    ;; Convert preloaded file names to absolute.
    (let ((lisp-dir
! 	 (file-truename
! 	  (file-name-directory
! 	   (locate-file "simple" load-path
! 			(get-load-suffixes))))))
  
      (setq load-history
  	  (mapcar (lambda (elt)
  		    (if (and (stringp (car elt))
  			     (not (file-name-absolute-p (car elt))))
  			(cons (concat lisp-dir
! 				      (car elt))
  			      (cdr elt))
  		      elt))
  		  load-history)))
Index: lisp/subr.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/subr.el,v
retrieving revision 1.507
diff -c -r1.507 subr.el
*** lisp/subr.el	7 May 2006 20:49:01 -0000	1.507
--- lisp/subr.el	14 May 2006 09:52:01 -0000
***************
*** 1385,1416 ****
  		 t))
       nil))
  
  (defun eval-after-load (file form)
    "Arrange that, if FILE is ever loaded, FORM will be run at that time.
- This makes or adds to an entry on `after-load-alist'.
  If FILE is already loaded, evaluate FORM right now.
! It does nothing if FORM is already on the list for FILE.
! FILE must match exactly.  Normally FILE is the name of a library,
! with no directory or extension specified, since that is how `load'
! is normally called.
! FILE can also be a feature (i.e. a symbol), in which case FORM is
! evaluated whenever that feature is `provide'd."
    (let ((elt (assoc file after-load-alist)))
-     ;; Make sure there is an element for FILE.
      (unless elt (setq elt (list file)) (push elt after-load-alist))
!     ;; Add FORM to the element if it isn't there.
      (unless (member form (cdr elt))
!       (nconc elt (list form))
!       ;; If the file has been loaded already, run FORM right away.
!       (if (if (symbolp file)
! 	      (featurep file)
! 	    ;; Make sure `load-history' contains the files dumped with
! 	    ;; Emacs for the case that FILE is one of them.
! 	    ;; (load-symbol-file-load-history)
! 	    (when (locate-library file)
! 	      (assoc (locate-library file) load-history)))
! 	  (eval form))))
!   form)
  
  (defun eval-next-after-load (file)
    "Read the following input sexp, and run it whenever FILE is loaded.
--- 1385,1494 ----
  		 t))
       nil))
  
+ (defun load-history-regexp (file)
+   "Form a regexp to find FILE in load-history.
+ FILE, a string, is described in eval-after-load's doc-string."
+   (if (file-name-absolute-p file)
+       (setq file (file-truename file)))
+   (concat (if (file-name-absolute-p file) "\\`" "\\<")
+ 	  (regexp-quote file)
+ 	  (if (file-name-extension file)
+ 	      ""
+ 	    (regexp-opt (cons "" load-suffixes)))
+ 	  "\\(" (regexp-opt jka-compr-load-suffixes) "\\)?\\'"))
+ 
+ (defun load-history-filename-element (file)
+   "Get the first element of load-history which matches FILE.
+ Return nil if there isn't one.
+ 
+ FILE, a string, is described in eval-after-load's doc-string."
+   (let* ((regexp (load-history-regexp file))
+ 	 (loads load-history)
+ 	 (load-elt (and loads (car loads))))
+     (save-match-data
+       (while (and loads
+ 		  (or (null (car load-elt))
+ 		      (not (string-match regexp (car load-elt)))))
+ 	(setq loads (cdr loads)
+ 	      load-elt (and loads (car loads)))))
+     load-elt))
+ 
+ (defun loaded-filename (file)
+   "Get the absolute file name from which Elisp file FILE was loaded.
+ Return nil if the file isn't found.  The returned file name will be a true
+ name \(i.e. with all its symbolic links having been chased out).
+ 
+ FILE is a string.  See eval-after-load for precise description."
+   (let ((elt (load-history-filename-element file)))
+     (and elt (car elt))))
+ 
  (defun eval-after-load (file form)
    "Arrange that, if FILE is ever loaded, FORM will be run at that time.
  If FILE is already loaded, evaluate FORM right now.
! 
! If a matching file is loaded again, FORM will be evaluated again.
! 
! If FILE is a string, it may be either an absolute or a relative file
! name, and may have an extension \(e.g. \".el\") or may lack one, and
! additionally may or may not have an extension denoting a compressed
! format \(e.g. \".gz\").
! 
! When FILE is absolute, it is first converted to a true name by chasing
! out symbolic links.  Only a file of this name \(see next paragraph for
! extensions) will trigger the evaluation of FORM.  When FILE is relative,
! a file whose absolute true name ends in FILE will trigger evaluation.
! 
! When FILE lacks an extension, a file name with any extension will trigger
! evaluation.  Otherwise, its extension must match FILE's.  A further
! extension for a compressed format \(e.g. \".gz\") on FILE will not affect
! this name matching.
! 
! Alternatively, FILE can be a feature (i.e. a symbol), in which case FORM
! is evaluated whenever that feature is `provide'd.
! 
! Usually FILE is just a library name like \"font-lock\" or a feature name
! like 'font-lock.
! 
! This function makes or adds to an entry on `after-load-alist'."
!   ;; Add this FORM into after-load-alist (regardless of whether we'll be
!   ;; evaluating it now).
    (let ((elt (assoc file after-load-alist)))
      (unless elt (setq elt (list file)) (push elt after-load-alist))
!     ;; Add FORM to the element unless it's already there.
      (unless (member form (cdr elt))
!       (nconc elt (list form))))
! 
!   ;; Is there an already loaded file whose name (or `provide' name)
!   ;; matches FILE?
!   (if (if (symbolp file)
! 	  (featurep file)
! 	(loaded-filename file))
!       (eval form)))
! 
! (defun get-after-load-alist-matches (abs-file)
!   "Get all the matches in after-load-alist for the file name ABS-FILE.
! ABS-FILE, a string, should be the absolute true name of a file just loaded."
!   (let ((elements after-load-alist)
! 	element result)
!     (while elements
!       (setq element (car elements))
!       (if (and (stringp (car element))
! 	       (string-match (load-history-regexp (car element)) abs-file))
! 	  (push element result))
!       (setq elements (cdr elements)))
!     (nreverse result)))
! 
! (defun do-after-load-evaluation (abs-file)
!   "Evaluate all `eval-after-load' forms, if any, for ABS-FILE.
! ABS-FILE, a string, should be the absolute true name of a file just loaded."
!   (let ((file-elements (get-after-load-alist-matches abs-file))
! 	file-element form)
!     (while file-elements
!       (setq file-element (car file-elements)
! 	    file-elements (cdr file-elements))
!       (while (setq file-element (cdr file-element)) ; discard the file name.
! 	(setq form (car file-element))
! 	(eval form)))))
  
  (defun eval-next-after-load (file)
    "Read the following input sexp, and run it whenever FILE is loaded.
Index: lisp/loadup.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/loadup.el,v
retrieving revision 1.148
diff -c -r1.148 loadup.el
*** lisp/loadup.el	20 Feb 2006 22:14:54 -0000	1.148
--- lisp/loadup.el	14 May 2006 09:52:02 -0000
***************
*** 211,216 ****
--- 211,217 ----
  (load "vc-hooks")
  (load "jka-cmpr-hook")
  (load "ediff-hook")
+ (load "emacs-lisp/regexp-opt")		; needed for Fload.
  (if (fboundp 'x-show-tip) (load "tooltip"))
  
  (message "%s" (garbage-collect))
Index: lisp/international/mule.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/international/mule.el,v
retrieving revision 1.234
diff -c -r1.234 mule.el
*** lisp/international/mule.el	21 Apr 2006 12:22:24 -0000	1.234
--- lisp/international/mule.el	14 May 2006 09:52:08 -0000
***************
*** 98,106 ****
  			 ))
  	(let (kill-buffer-hook kill-buffer-query-functions)
  	  (kill-buffer buffer)))
!       (let ((hook (assoc file after-load-alist)))
! 	(when hook
! 	  (mapcar (function eval) (cdr hook))))
        (unless (or nomessage noninteractive)
  	(if source
  	    (message "Loading %s (source)...done" file)
--- 98,105 ----
  			 ))
  	(let (kill-buffer-hook kill-buffer-query-functions)
  	  (kill-buffer buffer)))
!       (do-after-load-evaluation fullname)
!       
        (unless (or nomessage noninteractive)
  	(if source
  	    (message "Loading %s (source)...done" file)




2006-05-14  Alan Mackenzie  <acm@muc.de>

	* lread.c (Vload_history): Enhance doc-string to say that the file
	is the absolute truename of the loaded file.

	* lread.c (readevalloop): Call file-truename on the name for
	load-history, except at preloading time.

	* lread.c (Fload): At preloading time, preserve the extension of
	the filename which goes into load-history.  New variable
	hist_file_name.

	* lread.c (Fload): Do eval-after-load stuff by calling the lisp
	function do-after-load-evaluation.
	

Index: src/lread.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/lread.c,v
retrieving revision 1.350
diff -c -r1.350 lread.c
*** src/lread.c	27 Feb 2006 02:04:35 -0000	1.350
--- src/lread.c	14 May 2006 09:51:44 -0000
***************
*** 718,725 ****
    register int fd = -1;
    int count = SPECPDL_INDEX ();
    Lisp_Object temp;
!   struct gcpro gcpro1, gcpro2;
!   Lisp_Object found, efound;
    /* 1 means we printed the ".el is newer" message.  */
    int newer = 0;
    /* 1 means we are loading a compiled file.  */
--- 718,725 ----
    register int fd = -1;
    int count = SPECPDL_INDEX ();
    Lisp_Object temp;
!   struct gcpro gcpro1, gcpro2, gcpro3;
!   Lisp_Object found, efound, hist_file_name;
    /* 1 means we printed the ".el is newer" message.  */
    int newer = 0;
    /* 1 means we are loading a compiled file.  */
***************
*** 727,732 ****
--- 727,733 ----
    Lisp_Object handler;
    int safe_p = 1;
    char *fmode = "r";
+   Lisp_Object tmp[2];
  #ifdef DOS_NT
    fmode = "rt";
  #endif /* DOS_NT */
***************
*** 743,749 ****
       the need to gcpro noerror, nomessage and nosuffix.
       (Below here, we care only whether they are nil or not.)
       The presence of this call is the result of a historical accident:
!      it used to be in every file-operations and when it got removed
       everywhere, it accidentally stayed here.  Since then, enough people
       supposedly have things like (load "$PROJECT/foo.el") in their .emacs
       that it seemed risky to remove.  */
--- 744,750 ----
       the need to gcpro noerror, nomessage and nosuffix.
       (Below here, we care only whether they are nil or not.)
       The presence of this call is the result of a historical accident:
!      it used to be in every file-operation and when it got removed
       everywhere, it accidentally stayed here.  Since then, enough people
       supposedly have things like (load "$PROJECT/foo.el") in their .emacs
       that it seemed risky to remove.  */
***************
*** 763,769 ****
    if (SCHARS (file) > 0)
      {
        int size = SBYTES (file);
-       Lisp_Object tmp[2];
  
        found = Qnil;
        GCPRO2 (file, found);
--- 764,769 ----
***************
*** 847,852 ****
--- 847,859 ----
      Vloads_in_progress = Fcons (found, Vloads_in_progress);
    }
  
+   /* Get the name for load-history. */
+   hist_file_name = (! NILP (Vpurify_flag)
+                     ? Fconcat (2, (tmp[0] = Ffile_name_directory (file),
+                                    tmp[1] = Ffile_name_nondirectory (found),
+                                    tmp))
+                     : found) ;
+ 
    if (!bcmp (SDATA (found) + SBYTES (found) - 4,
  	     ".elc", 4))
      /* Load .elc files directly, but not when they are
***************
*** 857,863 ****
  	  struct stat s1, s2;
  	  int result;
  
! 	  GCPRO2 (file, found);
  
  	  if (!safe_to_load_p (fd))
  	    {
--- 864,870 ----
  	  struct stat s1, s2;
  	  int result;
  
! 	  GCPRO3 (file, found, hist_file_name);
  
  	  if (!safe_to_load_p (fd))
  	    {
***************
*** 911,924 ****
  
  	  if (fd >= 0)
  	    emacs_close (fd);
! 	  val = call4 (Vload_source_file_function, found, file,
  		       NILP (noerror) ? Qnil : Qt,
  		       NILP (nomessage) ? Qnil : Qt);
  	  return unbind_to (count, val);
  	}
      }
  
!   GCPRO2 (file, found);
  
  #ifdef WINDOWSNT
    emacs_close (fd);
--- 918,931 ----
  
  	  if (fd >= 0)
  	    emacs_close (fd);
! 	  val = call4 (Vload_source_file_function, found, hist_file_name,
  		       NILP (noerror) ? Qnil : Qt,
  		       NILP (nomessage) ? Qnil : Qt);
  	  return unbind_to (count, val);
  	}
      }
  
!   GCPRO3 (file, found, hist_file_name);
  
  #ifdef WINDOWSNT
    emacs_close (fd);
***************
*** 957,970 ****
    load_descriptor_list
      = Fcons (make_number (fileno (stream)), load_descriptor_list);
    load_in_progress++;
!   readevalloop (Qget_file_char, stream, (! NILP (Vpurify_flag) ? file : found),
  		Feval, 0, Qnil, Qnil, Qnil, Qnil);
    unbind_to (count, Qnil);
  
!   /* Run any load-hooks for this file.  */
!   temp = Fassoc (file, Vafter_load_alist);
!   if (!NILP (temp))
!     Fprogn (Fcdr (temp));
    UNGCPRO;
  
    if (saved_doc_string)
--- 964,986 ----
    load_descriptor_list
      = Fcons (make_number (fileno (stream)), load_descriptor_list);
    load_in_progress++;
!   readevalloop (Qget_file_char, stream, hist_file_name,
  		Feval, 0, Qnil, Qnil, Qnil, Qnil);
    unbind_to (count, Qnil);
  
!   /* Run any eval-after-load forms for this file */
!   if (NILP (Vpurify_flag))
!   {
!     Lisp_Object Qdo_after_load_evaluation
!       = intern ("do-after-load-evaluation") ;
!     if (!NILP (Ffboundp (Qdo_after_load_evaluation)))
!       call1 (Qdo_after_load_evaluation, hist_file_name) ;
!      else
!        Fsignal (Qerror,
!                 Fcons (make_string
!                        ("Fload: can't find do-after-load-evaluation",
!                         42), Qnil)) ;
!   }
    UNGCPRO;
  
    if (saved_doc_string)
***************
*** 1385,1390 ****
--- 1401,1414 ----
  
    GCPRO4 (sourcename, readfun, start, end);
  
+   /* Try to ensure sourcename is a truename, except whilst preloading. */
+   if (NILP (Vpurify_flag) && !NILP (sourcename)
+       && Ffile_name_absolute_p (sourcename))
+     {
+       Lisp_Object Qfile_truename = intern ("file-truename") ;
+       if (!NILP (Ffboundp (Qfile_truename)))
+         sourcename = call1 (Qfile_truename, sourcename) ;
+     }
    LOADHIST_ATTACH (sourcename);
  
    continue_reading_p = 1;
***************
*** 3982,3987 ****
--- 4006,4015 ----
  Each alist element is a list that starts with a file name,
  except for one element (optional) that starts with nil and describes
  definitions evaluated from buffers not visiting files.
+ 
+ The file name is absolute and is the true file name (i.e. it doesn't
+ contain symbolic links) of the loaded file.
+ 
  The remaining elements of each list are symbols defined as variables
  and cons cells of the form `(provide . FEATURE)', `(require . FEATURE)',
  `(defun . FUNCTION)', `(autoload . SYMBOL)', and `(t . SYMBOL)'.

Index: src/puresize.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/puresize.h,v
retrieving revision 1.86
diff -c -r1.86 puresize.h
*** src/puresize.h	22 Apr 2006 10:09:36 -0000	1.86
--- src/puresize.h	14 May 2006 09:51:44 -0000
***************
*** 43,49 ****
  #endif
  
  #ifndef BASE_PURESIZE
! #define BASE_PURESIZE (1205000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA)
  #endif
  
  /* Increase BASE_PURESIZE by a ratio depending on the machine's word size.  */
--- 43,51 ----
  #endif
  
  #ifndef BASE_PURESIZE
! #define BASE_PURESIZE (1210000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) 
! /* was (1205000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA).  Increased
!    for regexp-opt, ACM, 2006/5/13 */
  #endif
  
  /* Increase BASE_PURESIZE by a ratio depending on the machine's word size.  */




-- 
>Alan.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: FIXED!! Re: Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
  2006-05-14 11:07 ` FIXED!! " Alan Mackenzie
@ 2006-05-15  5:13   ` Richard Stallman
  2006-05-21  9:39     ` Alan Mackenzie
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Stallman @ 2006-05-15  5:13 UTC (permalink / raw)
  Cc: emacs-devel

What is the motive for computing the truename in Fload?

I don't like the use of regexp-opt.  Can you get rid of that?

The function loaded-filename does not seem very useful,
and is easy to get rid of, so would you please do so?

    !     Lisp_Object Qdo_after_load_evaluation
    !       = intern ("do-after-load-evaluation") ;

That symbol should be file-scope, and initialized in
syms_of_lread, in the normal way.

    !      else
    !        Fsignal (Qerror,
    !                 Fcons (make_string
    !                        ("Fload: can't find do-after-load-evaluation",
    !                         42), Qnil)) ;
    !   }

It should do nothing, not signal an error.

    +       Lisp_Object Qfile_truename = intern ("file-truename") ;

Likewise here.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: FIXED!! Re: Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
  2006-05-15  5:13   ` Richard Stallman
@ 2006-05-21  9:39     ` Alan Mackenzie
  2006-05-22  2:39       ` Richard Stallman
  0 siblings, 1 reply; 14+ messages in thread
From: Alan Mackenzie @ 2006-05-21  9:39 UTC (permalink / raw)
  Cc: emacs-devel

Happy Sunday, Richard!

On Mon, 15 May 2006, Richard Stallman wrote:

>What is the motive for computing the truename in Fload?

So that the file names recorded in load-history are consistently true
names.  Previously, "M-x load-file ~/emacs/emacs/lisp/progmodes/cc-mode"
had put these inconsistent entries into load history:

"/home/acm/emacs/emacs/lisp/progmodes/cc-mode.elc"
"/mnt/hda7/emacs/lisp/progmodes/cc-fonts.elc"

, where both files are in the same directory (/home/acm/emacs being a
symlink to /mnt/hda7).  This is bad in and of itself, but additionally it
would screw up on

(eval-after-load "/mnt/hda7/emacs/lisp/progmodes/cc-mode" ....).

#########################################################################

>I don't like the use of regexp-opt.  Can you get rid of that?

I'm not quite sure exactly what you don't like about it.  Given that I'm
doing regexp matches on the filenames, it's not practical to eliminate
it.  I'm guessing that you didn't like the way it was called for EVERY
element of after-load-alist, and called repeatedly for EVERY file that
was loaded.  Also, that you didn't like regexp-opt having to be
preloaded, thus forcing BASE_PURESIZE to be increased.

I've changed tactics now, so that after-load-alist contains the regexps
rather than the file names.  i.e., an after-load-alist element which used
to be this:

    ("help-mode" (define-key help-mode-map "\356" 'clone-buffer))

is now this:

    ("\\<help-mode\\(?:\\.elc?\\)?\\(\\.gz\\)?\\'"
      (define-key help-mode-map "\356" 'clone-buffer))

.  Thus this regexp is now only built once for each eval-after-load call,
and regexp-opt.elc doesn't need to be preloaded.

HOWEVER, regexp-opt.elc WASN'T BEING LOADED AT emacs START UP, thus
causing an error, because .../lisp/emacs-lisp isn't on load-path at emacs
start up.  I have worked around this by moving regexp-opt.{el,elc} from
.../lisp/emacs-lisp to ..../lisp.  (Though this isn't in the patch
below).

You might not like this relocation of regexp-opt.{el,elc}.  I don't know
what impact it might have on other things, but I can't see any problems
right now. 

Possibilities are:
(i) Move regexp-opt.elc into the main lisp directory.
(ii) Add ..../lisp/emacs-lisp to the virgin load-path.
(iii) Postpone the regexpification of preload eval-after-load filenames
until `command-line' (in startup.el), much like the way preload
load-history filenames are fleshed out to absolute names there.

My personal preference would be for (i).  (iii) would be the least work,
I think.

#########################################################################

>The function loaded-filename does not seem very useful,
>and is easy to get rid of, so would you please do so?

DONE.

>    !     Lisp_Object Qdo_after_load_evaluation
>    !       = intern ("do-after-load-evaluation") ;

>That symbol should be file-scope, and initialized in
>syms_of_lread, in the normal way.

>    !      else
>    !        Fsignal (Qerror,
>    !                 Fcons (make_string
>    !                        ("Fload: can't find do-after-load-evaluation",
>    !                         42), Qnil)) ;
>    !   }

Sorry about these.  They're now fixed.

>It should do nothing, not signal an error.

FIXED.

>    +       Lisp_Object Qfile_truename = intern ("file-truename") ;

>Likewise here.

LIKEWISE FIXED.

#########################################################################

Here then is the amended patch.  Note again that regexp-opt.elc must be
in ..../emacs/lisp for Emacs to start up properly.


2006-05-21  Alan Mackenzie  <acm@muc.de>

	* startup.el (command-line): For names of preloaded files, don't
	append ".elc" (now done in Fload), and call file-truename on the
	lisp directory.

	* subr.el (eval-after-load): Fix the doc-string.  Allow FILE to
	match ANY loaded file with the right name, not just those in
	load-path.  Put a regexp matching the file name into
	after-load-alist, rather than the name itself.

	* subr.el: New functions load-history-regexp,
	load-history-filename-element, get-after-load-alist-matches,
	do-after-load-evaluation.

	* international/mule.el (load-with-code-conversion): Do the
	eval-after-load stuff by calling do-after-load-evaluation.

Index: lisp/startup.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/startup.el,v
retrieving revision 1.407
diff -c -r1.407 startup.el
*** lisp/startup.el	5 May 2006 14:05:54 -0000	1.407
--- lisp/startup.el	20 May 2006 22:18:49 -0000
***************
*** 644,661 ****
  
    ;; Convert preloaded file names to absolute.
    (let ((lisp-dir
! 	 (file-name-directory
! 	  (locate-file "simple" load-path
! 		       (get-load-suffixes)))))
  
      (setq load-history
  	  (mapcar (lambda (elt)
  		    (if (and (stringp (car elt))
  			     (not (file-name-absolute-p (car elt))))
  			(cons (concat lisp-dir
! 				      (car elt)
! 				      (if (string-match "[.]el$" (car elt))
! 					  "" ".elc"))
  			      (cdr elt))
  		      elt))
  		  load-history)))
--- 644,660 ----
  
    ;; Convert preloaded file names to absolute.
    (let ((lisp-dir
! 	 (file-truename
! 	  (file-name-directory
! 	   (locate-file "simple" load-path
! 			(get-load-suffixes))))))
  
      (setq load-history
  	  (mapcar (lambda (elt)
  		    (if (and (stringp (car elt))
  			     (not (file-name-absolute-p (car elt))))
  			(cons (concat lisp-dir
! 				      (car elt))
  			      (cdr elt))
  		      elt))
  		  load-history)))
Index: lisp/subr.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/subr.el,v
retrieving revision 1.507
diff -c -r1.507 subr.el
*** lisp/subr.el	7 May 2006 20:49:01 -0000	1.507
--- lisp/subr.el	20 May 2006 22:19:00 -0000
***************
*** 1385,1416 ****
  		 t))
       nil))
  
  (defun eval-after-load (file form)
    "Arrange that, if FILE is ever loaded, FORM will be run at that time.
- This makes or adds to an entry on `after-load-alist'.
  If FILE is already loaded, evaluate FORM right now.
! It does nothing if FORM is already on the list for FILE.
! FILE must match exactly.  Normally FILE is the name of a library,
! with no directory or extension specified, since that is how `load'
! is normally called.
! FILE can also be a feature (i.e. a symbol), in which case FORM is
! evaluated whenever that feature is `provide'd."
!   (let ((elt (assoc file after-load-alist)))
!     ;; Make sure there is an element for FILE.
!     (unless elt (setq elt (list file)) (push elt after-load-alist))
!     ;; Add FORM to the element if it isn't there.
      (unless (member form (cdr elt))
!       (nconc elt (list form))
!       ;; If the file has been loaded already, run FORM right away.
!       (if (if (symbolp file)
! 	      (featurep file)
! 	    ;; Make sure `load-history' contains the files dumped with
! 	    ;; Emacs for the case that FILE is one of them.
! 	    ;; (load-symbol-file-load-history)
! 	    (when (locate-library file)
! 	      (assoc (locate-library file) load-history)))
! 	  (eval form))))
!   form)
  
  (defun eval-next-after-load (file)
    "Read the following input sexp, and run it whenever FILE is loaded.
--- 1385,1486 ----
  		 t))
       nil))
  
+ (defun load-history-regexp (file)
+   "Form a regexp to find FILE in load-history.
+ FILE, a string, is described in eval-after-load's doc-string."
+   (if (file-name-absolute-p file)
+       (setq file (file-truename file)))
+   (concat (if (file-name-absolute-p file) "\\`" "\\<")
+ 	  (regexp-quote file)
+ 	  (if (file-name-extension file)
+ 	      ""
+ 	    (regexp-opt (cons "" load-suffixes)))
+ 	  "\\(" (regexp-opt jka-compr-load-suffixes) "\\)?\\'"))
+ 
+ (defun load-history-filename-element (regexp)
+   "Get the first element of load-history whose first element \(a file
+ name) matches REGEXP.  Return nil if there isn't one."
+   (let* ((loads load-history)
+ 	 (load-elt (and loads (car loads))))
+     (save-match-data
+       (while (and loads
+ 		  (or (null (car load-elt))
+ 		      (not (string-match regexp (car load-elt)))))
+ 	(setq loads (cdr loads)
+ 	      load-elt (and loads (car loads)))))
+     load-elt))
+ 
  (defun eval-after-load (file form)
    "Arrange that, if FILE is ever loaded, FORM will be run at that time.
  If FILE is already loaded, evaluate FORM right now.
! 
! If a matching file is loaded again, FORM will be evaluated again.
! 
! If FILE is a string, it may be either an absolute or a relative file
! name, and may have an extension \(e.g. \".el\") or may lack one, and
! additionally may or may not have an extension denoting a compressed
! format \(e.g. \".gz\").
! 
! When FILE is absolute, it is first converted to a true name by chasing
! out symbolic links.  Only a file of this name \(see next paragraph for
! extensions) will trigger the evaluation of FORM.  When FILE is relative,
! a file whose absolute true name ends in FILE will trigger evaluation.
! 
! When FILE lacks an extension, a file name with any extension will trigger
! evaluation.  Otherwise, its extension must match FILE's.  A further
! extension for a compressed format \(e.g. \".gz\") on FILE will not affect
! this name matching.
! 
! Alternatively, FILE can be a feature (i.e. a symbol), in which case FORM
! is evaluated whenever that feature is `provide'd.
! 
! Usually FILE is just a library name like \"font-lock\" or a feature name
! like 'font-lock.
! 
! This function makes or adds to an entry on `after-load-alist'."
!   ;; Add this FORM into after-load-alist (regardless of whether we'll be
!   ;; evaluating it now).
!   (let* ((regexp-or-feature
! 	  (if (stringp file) (load-history-regexp file) file))
! 	 (elt (assoc regexp-or-feature after-load-alist)))
!     (unless elt
!       (setq elt (list regexp-or-feature))
!       (push elt after-load-alist))
!     ;; Add FORM to the element unless it's already there.
      (unless (member form (cdr elt))
!       (nconc elt (list form)))
! 
!     ;; Is there an already loaded file whose name (or `provide' name)
!     ;; matches FILE?
!     (if (if (stringp file)
! 	    (load-history-filename-element regexp-or-feature)
! 	  (featurep file))
! 	(eval form))))
! 
! (defun get-after-load-alist-matches (abs-file)
!   "Get all the matches in after-load-alist for the file name ABS-FILE.
! ABS-FILE, a string, should be the absolute true name of a file just loaded."
!   (let ((elements after-load-alist)
! 	element result)
!     (while elements
!       (setq element (car elements))
!       (if (and (stringp (car element))
! 	       (string-match (car element) abs-file))
! 	  (push element result))
!       (setq elements (cdr elements)))
!     (nreverse result)))
! 
! (defun do-after-load-evaluation (abs-file)
!   "Evaluate all `eval-after-load' forms, if any, for ABS-FILE.
! ABS-FILE, a string, should be the absolute true name of a file just loaded."
!   (let ((file-elements (get-after-load-alist-matches abs-file))
! 	file-element form)
!     (while file-elements
!       (setq file-element (car file-elements)
! 	    file-elements (cdr file-elements))
!       (while (setq file-element (cdr file-element)) ; discard the file name.
! 	(setq form (car file-element))
! 	(eval form)))))
  
  (defun eval-next-after-load (file)
    "Read the following input sexp, and run it whenever FILE is loaded.
Index: lisp/international/mule.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/international/mule.el,v
retrieving revision 1.234
diff -c -r1.234 mule.el
*** lisp/international/mule.el	21 Apr 2006 12:22:24 -0000	1.234
--- lisp/international/mule.el	20 May 2006 22:19:08 -0000
***************
*** 98,106 ****
  			 ))
  	(let (kill-buffer-hook kill-buffer-query-functions)
  	  (kill-buffer buffer)))
!       (let ((hook (assoc file after-load-alist)))
! 	(when hook
! 	  (mapcar (function eval) (cdr hook))))
        (unless (or nomessage noninteractive)
  	(if source
  	    (message "Loading %s (source)...done" file)
--- 98,106 ----
  			 ))
  	(let (kill-buffer-hook kill-buffer-query-functions)
  	  (kill-buffer buffer)))
!       (unless purify-flag
!  	(do-after-load-evaluation fullname))
!       
        (unless (or nomessage noninteractive)
  	(if source
  	    (message "Loading %s (source)...done" file)



2006-05-21  Alan Mackenzie  <acm@muc.de>

	* lread.c (Vload_history): Enhance doc-string to say that the file
	is the absolute truename of the loaded file.

	* lread.c (Vafter_load_alist): doc-string: state that an element
	now has a regexp to match file names, not a file name as such.

	* lread.c (readevalloop): Call file-truename on the name for
	load-history, except at preloading time.

	* lread.c (Fload): At preloading time, preserve the extension of
	the filename which goes into load-history.  New variable
	hist_file_name.

	* lread.c (Fload): Do eval-after-load stuff by calling the lisp
	function do-after-load-evaluation.

Index: src/lread.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/lread.c,v
retrieving revision 1.350
diff -c -r1.350 lread.c
*** src/lread.c	27 Feb 2006 02:04:35 -0000	1.350
--- src/lread.c	20 May 2006 22:18:43 -0000
***************
*** 87,92 ****
--- 87,93 ----
  Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
  Lisp_Object Qinhibit_file_name_operation;
  Lisp_Object Qeval_buffer_list, Veval_buffer_list;
+ Lisp_Object Qfile_truename, Qdo_after_load_evaluation; /* ACM 2006/5/16 */
  
  extern Lisp_Object Qevent_symbol_element_mask;
  extern Lisp_Object Qfile_exists_p;
***************
*** 718,725 ****
    register int fd = -1;
    int count = SPECPDL_INDEX ();
    Lisp_Object temp;
!   struct gcpro gcpro1, gcpro2;
!   Lisp_Object found, efound;
    /* 1 means we printed the ".el is newer" message.  */
    int newer = 0;
    /* 1 means we are loading a compiled file.  */
--- 719,726 ----
    register int fd = -1;
    int count = SPECPDL_INDEX ();
    Lisp_Object temp;
!   struct gcpro gcpro1, gcpro2, gcpro3;
!   Lisp_Object found, efound, hist_file_name;
    /* 1 means we printed the ".el is newer" message.  */
    int newer = 0;
    /* 1 means we are loading a compiled file.  */
***************
*** 727,732 ****
--- 728,734 ----
    Lisp_Object handler;
    int safe_p = 1;
    char *fmode = "r";
+   Lisp_Object tmp[2];
  #ifdef DOS_NT
    fmode = "rt";
  #endif /* DOS_NT */
***************
*** 743,749 ****
       the need to gcpro noerror, nomessage and nosuffix.
       (Below here, we care only whether they are nil or not.)
       The presence of this call is the result of a historical accident:
!      it used to be in every file-operations and when it got removed
       everywhere, it accidentally stayed here.  Since then, enough people
       supposedly have things like (load "$PROJECT/foo.el") in their .emacs
       that it seemed risky to remove.  */
--- 745,751 ----
       the need to gcpro noerror, nomessage and nosuffix.
       (Below here, we care only whether they are nil or not.)
       The presence of this call is the result of a historical accident:
!      it used to be in every file-operation and when it got removed
       everywhere, it accidentally stayed here.  Since then, enough people
       supposedly have things like (load "$PROJECT/foo.el") in their .emacs
       that it seemed risky to remove.  */
***************
*** 763,769 ****
    if (SCHARS (file) > 0)
      {
        int size = SBYTES (file);
-       Lisp_Object tmp[2];
  
        found = Qnil;
        GCPRO2 (file, found);
--- 765,770 ----
***************
*** 847,852 ****
--- 848,860 ----
      Vloads_in_progress = Fcons (found, Vloads_in_progress);
    }
  
+   /* Get the name for load-history. */
+   hist_file_name = (! NILP (Vpurify_flag)
+                     ? Fconcat (2, (tmp[0] = Ffile_name_directory (file),
+                                    tmp[1] = Ffile_name_nondirectory (found),
+                                    tmp))
+                     : found) ;
+ 
    if (!bcmp (SDATA (found) + SBYTES (found) - 4,
  	     ".elc", 4))
      /* Load .elc files directly, but not when they are
***************
*** 857,863 ****
  	  struct stat s1, s2;
  	  int result;
  
! 	  GCPRO2 (file, found);
  
  	  if (!safe_to_load_p (fd))
  	    {
--- 865,871 ----
  	  struct stat s1, s2;
  	  int result;
  
! 	  GCPRO3 (file, found, hist_file_name);
  
  	  if (!safe_to_load_p (fd))
  	    {
***************
*** 911,924 ****
  
  	  if (fd >= 0)
  	    emacs_close (fd);
! 	  val = call4 (Vload_source_file_function, found, file,
  		       NILP (noerror) ? Qnil : Qt,
  		       NILP (nomessage) ? Qnil : Qt);
  	  return unbind_to (count, val);
  	}
      }
  
!   GCPRO2 (file, found);
  
  #ifdef WINDOWSNT
    emacs_close (fd);
--- 919,932 ----
  
  	  if (fd >= 0)
  	    emacs_close (fd);
! 	  val = call4 (Vload_source_file_function, found, hist_file_name,
  		       NILP (noerror) ? Qnil : Qt,
  		       NILP (nomessage) ? Qnil : Qt);
  	  return unbind_to (count, val);
  	}
      }
  
!   GCPRO3 (file, found, hist_file_name);
  
  #ifdef WINDOWSNT
    emacs_close (fd);
***************
*** 957,970 ****
    load_descriptor_list
      = Fcons (make_number (fileno (stream)), load_descriptor_list);
    load_in_progress++;
!   readevalloop (Qget_file_char, stream, (! NILP (Vpurify_flag) ? file : found),
  		Feval, 0, Qnil, Qnil, Qnil, Qnil);
    unbind_to (count, Qnil);
  
!   /* Run any load-hooks for this file.  */
!   temp = Fassoc (file, Vafter_load_alist);
!   if (!NILP (temp))
!     Fprogn (Fcdr (temp));
    UNGCPRO;
  
    if (saved_doc_string)
--- 965,979 ----
    load_descriptor_list
      = Fcons (make_number (fileno (stream)), load_descriptor_list);
    load_in_progress++;
!   readevalloop (Qget_file_char, stream, hist_file_name,
  		Feval, 0, Qnil, Qnil, Qnil, Qnil);
    unbind_to (count, Qnil);
  
!   /* Run any eval-after-load forms for this file */
!   if (NILP (Vpurify_flag)
!       && (!NILP (Ffboundp (Qdo_after_load_evaluation))))
!     call1 (Qdo_after_load_evaluation, hist_file_name) ;
! 
    UNGCPRO;
  
    if (saved_doc_string)
***************
*** 1385,1390 ****
--- 1394,1405 ----
  
    GCPRO4 (sourcename, readfun, start, end);
  
+   /* Try to ensure sourcename is a truename, except whilst preloading. */
+   if (NILP (Vpurify_flag)
+       && !NILP (sourcename) && Ffile_name_absolute_p (sourcename)
+       && (!NILP (Ffboundp (Qfile_truename))))
+     sourcename = call1 (Qfile_truename, sourcename) ;
+ 
    LOADHIST_ATTACH (sourcename);
  
    continue_reading_p = 1;
***************
*** 3965,3980 ****
  
    DEFVAR_LISP ("after-load-alist", &Vafter_load_alist,
  	       doc: /* An alist of expressions to be evalled when particular files are loaded.
! Each element looks like (FILENAME FORMS...).
! When `load' is run and the file-name argument is FILENAME,
! the FORMS in the corresponding element are executed at the end of loading.
! 
! FILENAME must match exactly!  Normally FILENAME is the name of a library,
! with no directory specified, since that is how `load' is normally called.
! An error in FORMS does not undo the load,
! but does prevent execution of the rest of the FORMS.
! FILENAME can also be a symbol (a feature) and FORMS are then executed
! when the corresponding call to `provide' is made.  */);
    Vafter_load_alist = Qnil;
  
    DEFVAR_LISP ("load-history", &Vload_history,
--- 3980,3996 ----
  
    DEFVAR_LISP ("after-load-alist", &Vafter_load_alist,
  	       doc: /* An alist of expressions to be evalled when particular files are loaded.
! Each element looks like (REGEXP-OR-FEATURE FORMS...).
! 
! REGEXP-OR-FEATURE is either a regular expression to match file names, or
! a symbol \(a feature name).
! 
! When `load' is run and the file-name argument matches an element's
! REGEXP-OR-FEATURE, or when `provide' is run and provides the symbol
! REGEXP-OR-FEATURE, the FORMS in the element are executed.
! 
! An error in FORMS does not undo the load, but does prevent execution of
! the rest of the FORMS.  */);
    Vafter_load_alist = Qnil;
  
    DEFVAR_LISP ("load-history", &Vload_history,
***************
*** 3982,3987 ****
--- 3998,4007 ----
  Each alist element is a list that starts with a file name,
  except for one element (optional) that starts with nil and describes
  definitions evaluated from buffers not visiting files.
+ 
+ The file name is absolute and is the true file name (i.e. it doesn't
+ contain symbolic links) of the loaded file.
+ 
  The remaining elements of each list are symbols defined as variables
  and cons cells of the form `(provide . FEATURE)', `(require . FEATURE)',
  `(defun . FUNCTION)', `(autoload . SYMBOL)', and `(t . SYMBOL)'.
***************
*** 4112,4117 ****
--- 4132,4143 ----
    Qeval_buffer_list = intern ("eval-buffer-list");
    staticpro (&Qeval_buffer_list);
  
+   Qfile_truename = intern ("file-truename");
+   staticpro (&Qfile_truename) ;
+ 
+   Qdo_after_load_evaluation = intern ("do-after-load-evaluation");
+   staticpro (&Qdo_after_load_evaluation) ;
+ 
    staticpro (&dump_path);
  
    staticpro (&read_objects);



-- 
Alan.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: FIXED!! Re: Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
  2006-05-21  9:39     ` Alan Mackenzie
@ 2006-05-22  2:39       ` Richard Stallman
  2006-05-23 17:21         ` Alan Mackenzie
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Stallman @ 2006-05-22  2:39 UTC (permalink / raw)
  Cc: emacs-devel

    >I don't like the use of regexp-opt.  Can you get rid of that?

    I'm not quite sure exactly what you don't like about it.

I don't like having to load it in order for Emacs to start up.
I am sure this can be implemented some other way.

    .  Thus this regexp is now only built once for each eval-after-load call,
    and regexp-opt.elc doesn't need to be preloaded.

That is somewhat of an improvement; but given how limited your use
of these regexps is, can't you construct them without regexp-opt?
I think that won't really be hard.

    HOWEVER, regexp-opt.elc WASN'T BEING LOADED AT emacs START UP, thus
    causing an error, because .../lisp/emacs-lisp isn't on load-path at emacs
    start up.

Avoiding the use of regexp-opt would eliminate the need for this, too.

Please try that; I think you will find it is not very hard.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: FIXED!! Re: Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
  2006-05-22  2:39       ` Richard Stallman
@ 2006-05-23 17:21         ` Alan Mackenzie
  2006-05-23 17:51           ` Andreas Schwab
  0 siblings, 1 reply; 14+ messages in thread
From: Alan Mackenzie @ 2006-05-23 17:21 UTC (permalink / raw)
  Cc: emacs-devel

Hi, Richard!

On Sun, 21 May 2006, Richard Stallman wrote:

>    >I don't like the use of regexp-opt.  Can you get rid of that?

>    I'm not quite sure exactly what you don't like about it.

>I don't like having to load it in order for Emacs to start up.
>I am sure this can be implemented some other way.

Oh, you're a hard taskmaster.  ;-)

>    .  Thus this regexp is now only built once for each eval-after-load call,
>    and regexp-opt.elc doesn't need to be preloaded.

>That is somewhat of an improvement; but given how limited your use
>of these regexps is, can't you construct them without regexp-opt?
>I think that won't really be hard.

You're right.  It wasn't hard.  I've written my own cut down
"regexp-pess" (called list-to-regexp) to take its place.  I had
overlooked the fact that regexp-quote was a primitive function, and hence
available.

So, I think we're there, now.  I don't think an entry in NEWS is
warranted; true, the semantics of after-load-alist have been changed, but
I don't really see that this alist is an "external" structure.  However,
I'll need to amend gnus/mm-util.el around L383, which (rather naughtily,
IMAO) misuses after-load-alist.  But first, would you please comment on
the patch as it now is.  Should I commit it?


2006-05-23  Alan Mackenzie  <acm@muc.de>

	* startup.el (command-line): For names of preloaded files, don't
	append ".elc" (now done in Fload), and call file-truename on the
	lisp directory.

	* subr.el (eval-after-load): Fix the doc-string.  Allow FILE to
	match ANY loaded file with the right name, not just those in
	load-path.  Put a regexp matching the file name into
	after-load-alist, rather than the name itself.

	* subr.el: New functions list-to-regexp, load-history-regexp,
	load-history-filename-element, get-after-load-alist-matches,
	do-after-load-evaluation.

	* international/mule.el (load-with-code-conversion): Do the
	eval-after-load stuff by calling do-after-load-evaluation.


Index: lisp/startup.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/startup.el,v
retrieving revision 1.407
diff -c -r1.407 startup.el
*** lisp/startup.el	5 May 2006 14:05:54 -0000	1.407
--- lisp/startup.el	23 May 2006 14:52:02 -0000
***************
*** 644,661 ****
  
    ;; Convert preloaded file names to absolute.
    (let ((lisp-dir
! 	 (file-name-directory
! 	  (locate-file "simple" load-path
! 		       (get-load-suffixes)))))
  
      (setq load-history
  	  (mapcar (lambda (elt)
  		    (if (and (stringp (car elt))
  			     (not (file-name-absolute-p (car elt))))
  			(cons (concat lisp-dir
! 				      (car elt)
! 				      (if (string-match "[.]el$" (car elt))
! 					  "" ".elc"))
  			      (cdr elt))
  		      elt))
  		  load-history)))
--- 644,660 ----
  
    ;; Convert preloaded file names to absolute.
    (let ((lisp-dir
! 	 (file-truename
! 	  (file-name-directory
! 	   (locate-file "simple" load-path
! 			(get-load-suffixes))))))
  
      (setq load-history
  	  (mapcar (lambda (elt)
  		    (if (and (stringp (car elt))
  			     (not (file-name-absolute-p (car elt))))
  			(cons (concat lisp-dir
! 				      (car elt))
  			      (cdr elt))
  		      elt))
  		  load-history)))

Index: lisp/subr.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/subr.el,v
retrieving revision 1.507
diff -c -r1.507 subr.el
*** lisp/subr.el	7 May 2006 20:49:01 -0000	1.507
--- lisp/subr.el	23 May 2006 14:52:13 -0000
***************
*** 1385,1416 ****
  		 t))
       nil))
  
  (defun eval-after-load (file form)
    "Arrange that, if FILE is ever loaded, FORM will be run at that time.
- This makes or adds to an entry on `after-load-alist'.
  If FILE is already loaded, evaluate FORM right now.
! It does nothing if FORM is already on the list for FILE.
! FILE must match exactly.  Normally FILE is the name of a library,
! with no directory or extension specified, since that is how `load'
! is normally called.
! FILE can also be a feature (i.e. a symbol), in which case FORM is
! evaluated whenever that feature is `provide'd."
!   (let ((elt (assoc file after-load-alist)))
!     ;; Make sure there is an element for FILE.
!     (unless elt (setq elt (list file)) (push elt after-load-alist))
!     ;; Add FORM to the element if it isn't there.
      (unless (member form (cdr elt))
!       (nconc elt (list form))
!       ;; If the file has been loaded already, run FORM right away.
!       (if (if (symbolp file)
! 	      (featurep file)
! 	    ;; Make sure `load-history' contains the files dumped with
! 	    ;; Emacs for the case that FILE is one of them.
! 	    ;; (load-symbol-file-load-history)
! 	    (when (locate-library file)
! 	      (assoc (locate-library file) load-history)))
! 	  (eval form))))
!   form)
  
  (defun eval-next-after-load (file)
    "Read the following input sexp, and run it whenever FILE is loaded.
--- 1385,1499 ----
  		 t))
       nil))
  
+ (defun list-to-regexp (arg)
+   "Build a regexp that matches any of the elements of ARG, a list of strings."
+   (if arg
+       (let ((regexp "\\("))
+ 	(mapc (lambda (elt)
+ 		(setq regexp (concat regexp (regexp-quote elt) "\\|")))
+ 	      arg)
+ 	(aset regexp (1- (length regexp)) ?\))
+ 	regexp)
+     ""))
+ 
+ (defun load-history-regexp (file)
+   "Form a regexp to find FILE in load-history.
+ FILE, a string, is described in eval-after-load's doc-string."
+   (if (file-name-absolute-p file)
+       (setq file (file-truename file)))
+   (concat (if (file-name-absolute-p file) "\\`" "\\<")
+ 	  (regexp-quote file)
+ 	  (if (file-name-extension file)
+ 	      ""
+ 	    ;; Note: regexp-opt can't be used here, since we need to call
+ 	    ;; this before Emacs has been fully started.  2006-05-21
+ 	    (concat (list-to-regexp load-suffixes) "?"))
+ 	  (list-to-regexp jka-compr-load-suffixes) "?\\'"))
+ 
+ (defun load-history-filename-element (regexp)
+   "Get the first element of load-history whose first element \(a file
+ name) matches REGEXP.  Return nil if there isn't one."
+   (let* ((loads load-history)
+ 	 (load-elt (and loads (car loads))))
+     (save-match-data
+       (while (and loads
+ 		  (or (null (car load-elt))
+ 		      (not (string-match regexp (car load-elt)))))
+ 	(setq loads (cdr loads)
+ 	      load-elt (and loads (car loads)))))
+     load-elt))
+ 
  (defun eval-after-load (file form)
    "Arrange that, if FILE is ever loaded, FORM will be run at that time.
  If FILE is already loaded, evaluate FORM right now.
! 
! If a matching file is loaded again, FORM will be evaluated again.
! 
! If FILE is a string, it may be either an absolute or a relative file
! name, and may have an extension \(e.g. \".el\") or may lack one, and
! additionally may or may not have an extension denoting a compressed
! format \(e.g. \".gz\").
! 
! When FILE is absolute, it is first converted to a true name by chasing
! out symbolic links.  Only a file of this name \(see next paragraph for
! extensions) will trigger the evaluation of FORM.  When FILE is relative,
! a file whose absolute true name ends in FILE will trigger evaluation.
! 
! When FILE lacks an extension, a file name with any extension will trigger
! evaluation.  Otherwise, its extension must match FILE's.  A further
! extension for a compressed format \(e.g. \".gz\") on FILE will not affect
! this name matching.
! 
! Alternatively, FILE can be a feature (i.e. a symbol), in which case FORM
! is evaluated whenever that feature is `provide'd.
! 
! Usually FILE is just a library name like \"font-lock\" or a feature name
! like 'font-lock.
! 
! This function makes or adds to an entry on `after-load-alist'."
!   ;; Add this FORM into after-load-alist (regardless of whether we'll be
!   ;; evaluating it now).
!   (let* ((regexp-or-feature
! 	  (if (stringp file) (load-history-regexp file) file))
! 	 (elt (assoc regexp-or-feature after-load-alist)))
!     (unless elt
!       (setq elt (list regexp-or-feature))
!       (push elt after-load-alist))
!     ;; Add FORM to the element unless it's already there.
      (unless (member form (cdr elt))
!       (nconc elt (list form)))
! 
!     ;; Is there an already loaded file whose name (or `provide' name)
!     ;; matches FILE?
!     (if (if (stringp file)
! 	    (load-history-filename-element regexp-or-feature)
! 	  (featurep file))
! 	(eval form))))
! 
! (defun get-after-load-alist-matches (abs-file)
!   "Get all the matches in after-load-alist for the file name ABS-FILE.
! ABS-FILE, a string, should be the absolute true name of a file just loaded."
!   (let ((elements after-load-alist)
! 	element result)
!     (while elements
!       (setq element (car elements))
!       (if (and (stringp (car element))
! 	       (string-match (car element) abs-file))
! 	  (push element result))
!       (setq elements (cdr elements)))
!     (nreverse result)))
! 
! (defun do-after-load-evaluation (abs-file)
!   "Evaluate all `eval-after-load' forms, if any, for ABS-FILE.
! ABS-FILE, a string, should be the absolute true name of a file just loaded."
!   (let ((file-elements (get-after-load-alist-matches abs-file))
! 	file-element form)
!     (while file-elements
!       (setq file-element (car file-elements)
! 	    file-elements (cdr file-elements))
!       (while (setq file-element (cdr file-element)) ; discard the file name.
! 	(setq form (car file-element))
! 	(eval form)))))
  
  (defun eval-next-after-load (file)
    "Read the following input sexp, and run it whenever FILE is loaded.
Index: lisp/international/mule.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/international/mule.el,v
retrieving revision 1.234
diff -c -r1.234 mule.el
*** lisp/international/mule.el	21 Apr 2006 12:22:24 -0000	1.234
--- lisp/international/mule.el	23 May 2006 14:52:21 -0000
***************
*** 98,106 ****
  			 ))
  	(let (kill-buffer-hook kill-buffer-query-functions)
  	  (kill-buffer buffer)))
!       (let ((hook (assoc file after-load-alist)))
! 	(when hook
! 	  (mapcar (function eval) (cdr hook))))
        (unless (or nomessage noninteractive)
  	(if source
  	    (message "Loading %s (source)...done" file)
--- 98,106 ----
  			 ))
  	(let (kill-buffer-hook kill-buffer-query-functions)
  	  (kill-buffer buffer)))
!       (unless purify-flag
!  	(do-after-load-evaluation fullname))
!       
        (unless (or nomessage noninteractive)
  	(if source
  	    (message "Loading %s (source)...done" file)


2006-05-21  Alan Mackenzie  <acm@muc.de>

	* lread.c (Vload_history): Enhance doc-string to say that the file
	is the absolute truename of the loaded file.

	* lread.c (Vafter_load_alist): doc-string: state that an element
	now has a regexp to match file names, not a file name as such.

	* lread.c (readevalloop): Call file-truename on the name for
	load-history, except at preloading time.

	* lread.c (Fload): At preloading time, preserve the extension of
	the filename which goes into load-history.  New variable
	hist_file_name.

	* lread.c (Fload): Do eval-after-load stuff by calling the lisp
	function do-after-load-evaluation.


Index: src/lread.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/lread.c,v
retrieving revision 1.350
diff -c -r1.350 lread.c
*** src/lread.c	27 Feb 2006 02:04:35 -0000	1.350
--- src/lread.c	23 May 2006 14:51:57 -0000
***************
*** 87,92 ****
--- 87,93 ----
  Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
  Lisp_Object Qinhibit_file_name_operation;
  Lisp_Object Qeval_buffer_list, Veval_buffer_list;
+ Lisp_Object Qfile_truename, Qdo_after_load_evaluation; /* ACM 2006/5/16 */
  
  extern Lisp_Object Qevent_symbol_element_mask;
  extern Lisp_Object Qfile_exists_p;
***************
*** 718,725 ****
    register int fd = -1;
    int count = SPECPDL_INDEX ();
    Lisp_Object temp;
!   struct gcpro gcpro1, gcpro2;
!   Lisp_Object found, efound;
    /* 1 means we printed the ".el is newer" message.  */
    int newer = 0;
    /* 1 means we are loading a compiled file.  */
--- 719,726 ----
    register int fd = -1;
    int count = SPECPDL_INDEX ();
    Lisp_Object temp;
!   struct gcpro gcpro1, gcpro2, gcpro3;
!   Lisp_Object found, efound, hist_file_name;
    /* 1 means we printed the ".el is newer" message.  */
    int newer = 0;
    /* 1 means we are loading a compiled file.  */
***************
*** 727,732 ****
--- 728,734 ----
    Lisp_Object handler;
    int safe_p = 1;
    char *fmode = "r";
+   Lisp_Object tmp[2];
  #ifdef DOS_NT
    fmode = "rt";
  #endif /* DOS_NT */
***************
*** 743,749 ****
       the need to gcpro noerror, nomessage and nosuffix.
       (Below here, we care only whether they are nil or not.)
       The presence of this call is the result of a historical accident:
!      it used to be in every file-operations and when it got removed
       everywhere, it accidentally stayed here.  Since then, enough people
       supposedly have things like (load "$PROJECT/foo.el") in their .emacs
       that it seemed risky to remove.  */
--- 745,751 ----
       the need to gcpro noerror, nomessage and nosuffix.
       (Below here, we care only whether they are nil or not.)
       The presence of this call is the result of a historical accident:
!      it used to be in every file-operation and when it got removed
       everywhere, it accidentally stayed here.  Since then, enough people
       supposedly have things like (load "$PROJECT/foo.el") in their .emacs
       that it seemed risky to remove.  */
***************
*** 763,769 ****
    if (SCHARS (file) > 0)
      {
        int size = SBYTES (file);
-       Lisp_Object tmp[2];
  
        found = Qnil;
        GCPRO2 (file, found);
--- 765,770 ----
***************
*** 847,852 ****
--- 848,860 ----
      Vloads_in_progress = Fcons (found, Vloads_in_progress);
    }
  
+   /* Get the name for load-history. */
+   hist_file_name = (! NILP (Vpurify_flag)
+                     ? Fconcat (2, (tmp[0] = Ffile_name_directory (file),
+                                    tmp[1] = Ffile_name_nondirectory (found),
+                                    tmp))
+                     : found) ;
+ 
    if (!bcmp (SDATA (found) + SBYTES (found) - 4,
  	     ".elc", 4))
      /* Load .elc files directly, but not when they are
***************
*** 857,863 ****
  	  struct stat s1, s2;
  	  int result;
  
! 	  GCPRO2 (file, found);
  
  	  if (!safe_to_load_p (fd))
  	    {
--- 865,871 ----
  	  struct stat s1, s2;
  	  int result;
  
! 	  GCPRO3 (file, found, hist_file_name);
  
  	  if (!safe_to_load_p (fd))
  	    {
***************
*** 911,924 ****
  
  	  if (fd >= 0)
  	    emacs_close (fd);
! 	  val = call4 (Vload_source_file_function, found, file,
  		       NILP (noerror) ? Qnil : Qt,
  		       NILP (nomessage) ? Qnil : Qt);
  	  return unbind_to (count, val);
  	}
      }
  
!   GCPRO2 (file, found);
  
  #ifdef WINDOWSNT
    emacs_close (fd);
--- 919,932 ----
  
  	  if (fd >= 0)
  	    emacs_close (fd);
! 	  val = call4 (Vload_source_file_function, found, hist_file_name,
  		       NILP (noerror) ? Qnil : Qt,
  		       NILP (nomessage) ? Qnil : Qt);
  	  return unbind_to (count, val);
  	}
      }
  
!   GCPRO3 (file, found, hist_file_name);
  
  #ifdef WINDOWSNT
    emacs_close (fd);
***************
*** 957,970 ****
    load_descriptor_list
      = Fcons (make_number (fileno (stream)), load_descriptor_list);
    load_in_progress++;
!   readevalloop (Qget_file_char, stream, (! NILP (Vpurify_flag) ? file : found),
  		Feval, 0, Qnil, Qnil, Qnil, Qnil);
    unbind_to (count, Qnil);
  
!   /* Run any load-hooks for this file.  */
!   temp = Fassoc (file, Vafter_load_alist);
!   if (!NILP (temp))
!     Fprogn (Fcdr (temp));
    UNGCPRO;
  
    if (saved_doc_string)
--- 965,979 ----
    load_descriptor_list
      = Fcons (make_number (fileno (stream)), load_descriptor_list);
    load_in_progress++;
!   readevalloop (Qget_file_char, stream, hist_file_name,
  		Feval, 0, Qnil, Qnil, Qnil, Qnil);
    unbind_to (count, Qnil);
  
!   /* Run any eval-after-load forms for this file */
!   if (NILP (Vpurify_flag)
!       && (!NILP (Ffboundp (Qdo_after_load_evaluation))))
!     call1 (Qdo_after_load_evaluation, hist_file_name) ;
! 
    UNGCPRO;
  
    if (saved_doc_string)
***************
*** 1385,1390 ****
--- 1394,1405 ----
  
    GCPRO4 (sourcename, readfun, start, end);
  
+   /* Try to ensure sourcename is a truename, except whilst preloading. */
+   if (NILP (Vpurify_flag)
+       && !NILP (sourcename) && Ffile_name_absolute_p (sourcename)
+       && (!NILP (Ffboundp (Qfile_truename))))
+     sourcename = call1 (Qfile_truename, sourcename) ;
+ 
    LOADHIST_ATTACH (sourcename);
  
    continue_reading_p = 1;
***************
*** 3965,3980 ****
  
    DEFVAR_LISP ("after-load-alist", &Vafter_load_alist,
  	       doc: /* An alist of expressions to be evalled when particular files are loaded.
! Each element looks like (FILENAME FORMS...).
! When `load' is run and the file-name argument is FILENAME,
! the FORMS in the corresponding element are executed at the end of loading.
! 
! FILENAME must match exactly!  Normally FILENAME is the name of a library,
! with no directory specified, since that is how `load' is normally called.
! An error in FORMS does not undo the load,
! but does prevent execution of the rest of the FORMS.
! FILENAME can also be a symbol (a feature) and FORMS are then executed
! when the corresponding call to `provide' is made.  */);
    Vafter_load_alist = Qnil;
  
    DEFVAR_LISP ("load-history", &Vload_history,
--- 3980,3996 ----
  
    DEFVAR_LISP ("after-load-alist", &Vafter_load_alist,
  	       doc: /* An alist of expressions to be evalled when particular files are loaded.
! Each element looks like (REGEXP-OR-FEATURE FORMS...).
! 
! REGEXP-OR-FEATURE is either a regular expression to match file names, or
! a symbol \(a feature name).
! 
! When `load' is run and the file-name argument matches an element's
! REGEXP-OR-FEATURE, or when `provide' is run and provides the symbol
! REGEXP-OR-FEATURE, the FORMS in the element are executed.
! 
! An error in FORMS does not undo the load, but does prevent execution of
! the rest of the FORMS.  */);
    Vafter_load_alist = Qnil;
  
    DEFVAR_LISP ("load-history", &Vload_history,
***************
*** 3982,3987 ****
--- 3998,4007 ----
  Each alist element is a list that starts with a file name,
  except for one element (optional) that starts with nil and describes
  definitions evaluated from buffers not visiting files.
+ 
+ The file name is absolute and is the true file name (i.e. it doesn't
+ contain symbolic links) of the loaded file.
+ 
  The remaining elements of each list are symbols defined as variables
  and cons cells of the form `(provide . FEATURE)', `(require . FEATURE)',
  `(defun . FUNCTION)', `(autoload . SYMBOL)', and `(t . SYMBOL)'.
***************
*** 4112,4117 ****
--- 4132,4143 ----
    Qeval_buffer_list = intern ("eval-buffer-list");
    staticpro (&Qeval_buffer_list);
  
+   Qfile_truename = intern ("file-truename");
+   staticpro (&Qfile_truename) ;
+ 
+   Qdo_after_load_evaluation = intern ("do-after-load-evaluation");
+   staticpro (&Qdo_after_load_evaluation) ;
+ 
    staticpro (&dump_path);
  
    staticpro (&read_objects);

-- 
Alan.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: FIXED!! Re: Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
  2006-05-23 17:21         ` Alan Mackenzie
@ 2006-05-23 17:51           ` Andreas Schwab
  2006-05-23 20:10             ` Alan Mackenzie
  2006-05-23 20:58             ` FIXED!! Re: Clarification of eval-after-load Stefan Monnier
  0 siblings, 2 replies; 14+ messages in thread
From: Andreas Schwab @ 2006-05-23 17:51 UTC (permalink / raw)
  Cc: Richard Stallman, emacs-devel

Alan Mackenzie <acm@muc.de> writes:

> --- 1385,1499 ----
>   		 t))
>        nil))
>   
> + (defun list-to-regexp (arg)
> +   "Build a regexp that matches any of the elements of ARG, a list of strings."
> +   (if arg
> +       (let ((regexp "\\("))
> + 	(mapc (lambda (elt)
> + 		(setq regexp (concat regexp (regexp-quote elt) "\\|")))
> + 	      arg)
> + 	(aset regexp (1- (length regexp)) ?\))
> + 	regexp)
> +     ""))

I think this is equivalent to this:

  (concat "\\(" (mapconcat 'regexp-quote arg "\\|") "\\)")

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: FIXED!! Re: Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history]
  2006-05-23 17:51           ` Andreas Schwab
@ 2006-05-23 20:10             ` Alan Mackenzie
  2006-05-23 20:58             ` FIXED!! Re: Clarification of eval-after-load Stefan Monnier
  1 sibling, 0 replies; 14+ messages in thread
From: Alan Mackenzie @ 2006-05-23 20:10 UTC (permalink / raw)
  Cc: Richard Stallman, emacs-devel

'n Abend, Andreas!

On Tue, 23 May 2006, Andreas Schwab wrote:

>Alan Mackenzie <acm@muc.de> writes:
>
>> --- 1385,1499 ----
>>   		 t))
>>        nil))
>>   
>> + (defun list-to-regexp (arg)
>> +   "Build a regexp that matches any of the elements of ARG, a list of strings."
>> +   (if arg
>> +       (let ((regexp "\\("))
>> + 	(mapc (lambda (elt)
>> + 		(setq regexp (concat regexp (regexp-quote elt) "\\|")))
>> + 	      arg)
>> + 	(aset regexp (1- (length regexp)) ?\))
>> + 	regexp)
>> +     ""))

>I think this is equivalent to this:
>
>  (concat "\\(" (mapconcat 'regexp-quote arg "\\|") "\\)")

Thanks!  I didn't know about mapconcat.

Even better, mapconcat is a built-in function, so there's no hassle with
order of loading files.el, or with CL or anything like that.

So yes, I'll put the form in that you suggest, since it's certainly an
improvement.

Thanks again!

>Andreas.

-- 
Alan.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: FIXED!! Re: Clarification of eval-after-load
  2006-05-23 17:51           ` Andreas Schwab
  2006-05-23 20:10             ` Alan Mackenzie
@ 2006-05-23 20:58             ` Stefan Monnier
  1 sibling, 0 replies; 14+ messages in thread
From: Stefan Monnier @ 2006-05-23 20:58 UTC (permalink / raw)
  Cc: Alan Mackenzie, Richard Stallman, emacs-devel

> I think this is equivalent to this:
>   (concat "\\(" (mapconcat 'regexp-quote arg "\\|") "\\)")

Not only it's equivalent, but it's mentioned in the docstring of regexp-opt.
I wouldn't bother defining a function for this one-liner.


        Stefan

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2006-05-23 20:58 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-10 21:11 Clarification of eval-after-load [was: Problem mit symlinks, locate-library and load-history] Alan Mackenzie
2006-05-11 16:46 ` Stuart D. Herring
2006-05-11 17:19   ` Alan Mackenzie
2006-05-11 17:46     ` Stuart D. Herring
2006-05-11 21:44       ` Alan Mackenzie
2006-05-12  4:15       ` Richard Stallman
2006-05-14 11:07 ` FIXED!! " Alan Mackenzie
2006-05-15  5:13   ` Richard Stallman
2006-05-21  9:39     ` Alan Mackenzie
2006-05-22  2:39       ` Richard Stallman
2006-05-23 17:21         ` Alan Mackenzie
2006-05-23 17:51           ` Andreas Schwab
2006-05-23 20:10             ` Alan Mackenzie
2006-05-23 20:58             ` FIXED!! Re: Clarification of eval-after-load Stefan Monnier

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).