From: "Davis Herring" <herring@lanl.gov>
To: rms@gnu.org
Cc: emacs-pretest-bug@gnu.org, sdl.web@gmail.com
Subject: Re: 23.0.50; savehist save invalid syntax
Date: Wed, 5 Sep 2007 11:16:20 -0700 (PDT) [thread overview]
Message-ID: <60848.128.165.123.18.1189016180.squirrel@webmail.lanl.gov> (raw)
In-Reply-To: <E1ISoC2-0006Gq-VQ@fencepost.gnu.org>
[-- Attachment #1: Type: text/plain, Size: 1712 bytes --]
> With this much complexity, my temptation would be to provide a
> print-readable function (or an optional argument to an existing
> printer)
> that signalled if it were asked to print something that has no read
> syntax.
>
> I wouldn't mind adding that feature if someone wants to do it.
> It should be controlled by a variable.
I've implemented that feature. I took Stefan's suggestion and made the
variable be a function that took over printing (or t for signaling as in
my original suggestion). The patch is attached; please bear with me as I
think it's my most complex foray into Emacs' C thus far and introduces a
new macro and such. It is, however, tested.
On a side note, I see that this is an extension of the variable
`print-readably' in XEmacs. It doesn't follow naming convention, but
perhaps my new variable `print-unreadable-function' should be named or
aliased to `print-readably' for compatibility.
Meanwhile, savehist needs to use this. It actually already has a hack in
it that uses `prin1' and `read' (or `print-readably' on XEmacs) to detect
unreadability; one could certainly use this instead of the new printing
feature. But for cleanliness and completeness, I removed that trick and
replaced it with handlers for the unreadable signals that, now, both
varities of Emacs will generate. (Of course, I also actually implemented
the code to skip unprintable history elements, instead of skipping the
entire history or so.) This second patch is completely untested because
I'm unfamiliar with savehist.
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.
[-- Attachment #2: print-unreadable.patch --]
[-- Type: application/octet-stream, Size: 7233 bytes --]
Index: print.c
===================================================================
RCS file: /sources/emacs/emacs/src/print.c,v
retrieving revision 1.237
diff -c -r1.237 print.c
*** print.c 29 Aug 2007 05:27:56 -0000 1.237
--- print.c 5 Sep 2007 18:03:24 -0000
***************
*** 163,168 ****
--- 163,174 ----
int print_number_index;
Lisp_Object Vprint_number_table;
+ /* Function to call to print objects with no read syntax. */
+ Lisp_Object Qprint_unreadable_function, Vprint_unreadable_function;
+ /* We can't use do-while(0) here, so use a dangling else. */
+ #define PRINT_UNREADABLE \
+ if (escapeflag && !NILP (Vprint_unreadable_function)) {unreadable = 1; break;} else
+
/* PRINT_NUMBER_OBJECT returns the I'th object in Vprint_number_table TABLE.
PRINT_NUMBER_STATUS returns the status of the I'th object in TABLE.
See the comment of the variable Vprint_number_table. */
***************
*** 1475,1480 ****
--- 1481,1489 ----
int escapeflag;
{
char buf[40];
+ /* If we're asked to make readable output, and we can't, and there's a
+ handler for that, set this. */
+ int unreadable = 0;
QUIT;
***************
*** 1883,1891 ****
{
if (escapeflag)
{
! strout ("#<process ", -1, -1, printcharfun, 0);
! print_string (XPROCESS (obj)->name, printcharfun);
! PRINTCHAR ('>');
}
else
print_string (XPROCESS (obj)->name, printcharfun);
--- 1892,1904 ----
{
if (escapeflag)
{
! if (NILP (Vprint_unreadable_function))
! {
! strout ("#<process ", -1, -1, printcharfun, 0);
! print_string (XPROCESS (obj)->name, printcharfun);
! PRINTCHAR ('>');
! }
! else unreadable = 1;
}
else
print_string (XPROCESS (obj)->name, printcharfun);
***************
*** 1949,1960 ****
--- 1962,1975 ----
}
else if (SUBRP (obj))
{
+ PRINT_UNREADABLE;
strout ("#<subr ", -1, -1, printcharfun, 0);
strout (XSUBR (obj)->symbol_name, -1, -1, printcharfun, 0);
PRINTCHAR ('>');
}
else if (WINDOWP (obj))
{
+ PRINT_UNREADABLE;
strout ("#<window ", -1, -1, printcharfun, 0);
sprintf (buf, "%ld", (long) XFASTINT (XWINDOW (obj)->sequence_number));
strout (buf, -1, -1, printcharfun, 0);
***************
*** 1967,1972 ****
--- 1982,1988 ----
}
else if (HASH_TABLE_P (obj))
{
+ PRINT_UNREADABLE;
struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
strout ("#<hash-table", -1, -1, printcharfun, 0);
if (SYMBOLP (h->test))
***************
*** 1987,1992 ****
--- 2003,2009 ----
}
else if (BUFFERP (obj))
{
+ PRINT_UNREADABLE;
if (NILP (XBUFFER (obj)->name))
strout ("#<killed buffer>", -1, -1, printcharfun, 0);
else if (escapeflag)
***************
*** 2000,2009 ****
--- 2017,2028 ----
}
else if (WINDOW_CONFIGURATIONP (obj))
{
+ PRINT_UNREADABLE;
strout ("#<window-configuration>", -1, -1, printcharfun, 0);
}
else if (FRAMEP (obj))
{
+ PRINT_UNREADABLE;
strout ((FRAME_LIVE_P (XFRAME (obj))
? "#<frame " : "#<dead frame "),
-1, -1, printcharfun, 0);
***************
*** 2062,2067 ****
--- 2081,2087 ----
switch (XMISCTYPE (obj))
{
case Lisp_Misc_Marker:
+ PRINT_UNREADABLE;
strout ("#<marker ", -1, -1, printcharfun, 0);
/* Do you think this is necessary? */
if (XMARKER (obj)->insertion_type != 0)
***************
*** 2079,2084 ****
--- 2099,2105 ----
break;
case Lisp_Misc_Overlay:
+ PRINT_UNREADABLE;
strout ("#<overlay ", -1, -1, printcharfun, 0);
if (! XMARKER (OVERLAY_START (obj))->buffer)
strout ("in no buffer", -1, -1, printcharfun, 0);
***************
*** 2097,2123 ****
--- 2118,2149 ----
/* Remaining cases shouldn't happen in normal usage, but let's print
them anyway for the benefit of the debugger. */
case Lisp_Misc_Free:
+ PRINT_UNREADABLE;
strout ("#<misc free cell>", -1, -1, printcharfun, 0);
break;
case Lisp_Misc_Intfwd:
+ PRINT_UNREADABLE;
sprintf (buf, "#<intfwd to %ld>", (long) *XINTFWD (obj)->intvar);
strout (buf, -1, -1, printcharfun, 0);
break;
case Lisp_Misc_Boolfwd:
+ PRINT_UNREADABLE;
sprintf (buf, "#<boolfwd to %s>",
(*XBOOLFWD (obj)->boolvar ? "t" : "nil"));
strout (buf, -1, -1, printcharfun, 0);
break;
case Lisp_Misc_Objfwd:
+ PRINT_UNREADABLE;
strout ("#<objfwd to ", -1, -1, printcharfun, 0);
print_object (*XOBJFWD (obj)->objvar, printcharfun, escapeflag);
PRINTCHAR ('>');
break;
case Lisp_Misc_Buffer_Objfwd:
+ PRINT_UNREADABLE;
strout ("#<buffer_objfwd to ", -1, -1, printcharfun, 0);
print_object (PER_BUFFER_VALUE (current_buffer,
XBUFFER_OBJFWD (obj)->offset),
***************
*** 2126,2131 ****
--- 2152,2158 ----
break;
case Lisp_Misc_Kboard_Objfwd:
+ PRINT_UNREADABLE;
strout ("#<kboard_objfwd to ", -1, -1, printcharfun, 0);
print_object (*(Lisp_Object *) ((char *) current_kboard
+ XKBOARD_OBJFWD (obj)->offset),
***************
*** 2134,2142 ****
--- 2161,2171 ----
break;
case Lisp_Misc_Buffer_Local_Value:
+ PRINT_UNREADABLE;
strout ("#<buffer_local_value ", -1, -1, printcharfun, 0);
goto do_buffer_local;
case Lisp_Misc_Some_Buffer_Local_Value:
+ PRINT_UNREADABLE;
strout ("#<some_buffer_local_value ", -1, -1, printcharfun, 0);
do_buffer_local:
strout ("[realvalue] ", -1, -1, printcharfun, 0);
***************
*** 2167,2172 ****
--- 2196,2202 ----
break;
case Lisp_Misc_Save_Value:
+ PRINT_UNREADABLE;
strout ("#<save_value ", -1, -1, printcharfun, 0);
sprintf(buf, "ptr=0x%08lx int=%d",
(unsigned long) XSAVE_VALUE (obj)->pointer,
***************
*** 2198,2203 ****
--- 2228,2247 ----
}
}
+ if (unreadable)
+ {
+ /* Suppress print-unreadable-function. If we have a real handler, it
+ has no need to call itself; if we're signaling, a debugger may need
+ to print what's not printable with the signal enabled! */
+ int count = SPECPDL_INDEX ();
+ Lisp_Object handler = Vprint_unreadable_function;
+ specbind (Qprint_unreadable_function, Qnil);
+ if (EQ (handler, Qt))
+ xsignal1 (Qinvalid_read_syntax, obj);
+ call2 (handler, obj, printcharfun);
+ unbind_to (count, Qnil);
+ }
+
print_depth--;
}
\f
***************
*** 2332,2337 ****
--- 2376,2390 ----
that need to be recorded in the table. */);
Vprint_number_table = Qnil;
+ DEFVAR_LISP ("print-unreadable-function", &Vprint_unreadable_function,
+ doc: /* A function to call to print objects having no read syntax.
+ It is called with two arguments: the object to print and the output stream.
+ If t, an error is signaled to prevent producing unreadable output.
+ If nil, hash notation is used. */);
+ Vprint_unreadable_function = Qnil;
+ Qprint_unreadable_function = intern ("print-unreadable-function");
+ staticpro (&Qprint_unreadable_function);
+
/* prin1_to_string_buffer initialized in init_buffer_once in buffer.c */
staticpro (&Vprin1_to_string_buffer);
[-- Attachment #3: savehist-unreadable.patch --]
[-- Type: application/octet-stream, Size: 3900 bytes --]
*** savehist.el 01 Aug 2007 11:08:24 -0600 1.21
--- savehist.el 05 Sep 2007 12:13:43 -0600
***************
*** 299,325 ****
(print-string-length nil)
(print-level nil)
(print-readably t)
! (print-quoted t))
;; Save the minibuffer histories, along with the value of
;; savehist-minibuffer-history-variables itself.
(when savehist-save-minibuffer-history
(prin1 `(setq savehist-minibuffer-history-variables
! ',savehist-minibuffer-history-variables)
! (current-buffer))
(insert ?\n)
(dolist (symbol savehist-minibuffer-history-variables)
(when (boundp symbol)
(let ((value (savehist-trim-history (symbol-value symbol))))
(when value ; don't save empty histories
! (prin1 `(setq ,symbol ',value) (current-buffer))
! (insert ?\n))))))
;; Save the additional variables.
(dolist (symbol savehist-additional-variables)
(when (boundp symbol)
! (let ((value (symbol-value symbol)))
! (when (savehist-printable value)
! (prin1 `(setq ,symbol ',value) (current-buffer))
! (insert ?\n))))))
;; If autosaving, avoid writing if nothing has changed since the
;; last write.
(let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion)))
--- 299,328 ----
(print-string-length nil)
(print-level nil)
(print-readably t)
! (print-quoted t)
! (print-unreadable-function t)
! (standard-output (current-buffer)))
;; Save the minibuffer histories, along with the value of
;; savehist-minibuffer-history-variables itself.
(when savehist-save-minibuffer-history
(prin1 `(setq savehist-minibuffer-history-variables
! ',savehist-minibuffer-history-variables))
(insert ?\n)
(dolist (symbol savehist-minibuffer-history-variables)
(when (boundp symbol)
(let ((value (savehist-trim-history (symbol-value symbol))))
(when value ; don't save empty histories
! (insert "(setq ")
! (prin1 symbol)
! (insert ?\n)
! (while value
! (and (savehist-prin1-readable (car value))
! (setq value (cdr value)) (insert " ")))
! (insert ?\)))))))
;; Save the additional variables.
(dolist (symbol savehist-additional-variables)
(when (boundp symbol)
! (savehist-prin1-readable `(setq ,symbol ',(symbol-value symbol)))))
;; If autosaving, avoid writing if nothing has changed since the
;; last write.
(let ((checksum (md5 (current-buffer) nil nil savehist-no-conversion)))
***************
*** 355,380 ****
(loop repeat history-length collect (pop value))
value))
! (defun savehist-printable (value)
! "Return non-nil if VALUE is printable."
! (cond
! ;; Quick response for oft-encountered types known to be printable.
! ((stringp value))
! ((numberp value))
! ((symbolp value))
! (t
! ;; For others, check explicitly.
! (with-temp-buffer
! (condition-case nil
! (let ((print-readably t) (print-level nil))
! ;; Print the value into a buffer...
(prin1 value (current-buffer))
! ;; ...and attempt to read it.
! (read (point-min-marker))
! ;; The attempt worked: the object is printable.
! t)
! ;; The attempt failed: the object is not printable.
! (error nil))))))
(defun savehist-minibuffer-hook ()
(unless (or (eq minibuffer-history-variable t)
--- 358,372 ----
(loop repeat history-length collect (pop value))
value))
! (defun savehist-prin1-readable (value)
! "Print VALUE in the current buffer, if it's readable.
! Return non-nil if it was printed."
! (let ((opoint (point)))
! (condition-case nil
! (progn
(prin1 value (current-buffer))
! (insert ?\n) t)
! (invalid-read-syntax (delete-region opoint (point)) nil))))
(defun savehist-minibuffer-hook ()
(unless (or (eq minibuffer-history-variable t)
[-- Attachment #4: Type: text/plain, Size: 142 bytes --]
_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel
next prev parent reply other threads:[~2007-09-05 18:16 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-02 10:38 23.0.50; savehist save invalid syntax Leo
2007-09-02 13:21 ` Drew Adams
2007-09-03 3:04 ` Richard Stallman
2007-09-04 22:48 ` Davis Herring
2007-09-05 3:20 ` Stefan Monnier
2007-09-05 6:16 ` Richard Stallman
2007-09-05 18:16 ` Davis Herring [this message]
2007-09-06 5:00 ` Richard Stallman
2007-09-09 21:58 ` Drew Adams
2007-09-09 23:14 ` Andreas Schwab
2007-09-10 3:01 ` Drew Adams
2007-09-10 3:07 ` Drew Adams
2007-09-10 22:11 ` Davis Herring
2007-09-10 23:42 ` Drew Adams
2007-09-10 23:54 ` Richard Stallman
2007-09-11 20:27 ` Davis Herring
2007-09-10 21:59 ` Davis Herring
2007-09-10 23:42 ` Drew Adams
2007-09-11 0:55 ` Davis Herring
2007-09-11 1:11 ` Stefan Monnier
2007-09-11 21:06 ` [Released] " Davis Herring
2007-09-11 21:29 ` Stefan Monnier
2007-09-14 7:04 ` Richard Stallman
2007-09-11 1:18 ` Drew Adams
2007-09-05 19:57 ` Leo
2007-10-18 21:08 ` Leo
2007-10-19 8:15 ` Leo
2007-10-19 14:01 ` Stefan Monnier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=60848.128.165.123.18.1189016180.squirrel@webmail.lanl.gov \
--to=herring@lanl.gov \
--cc=emacs-pretest-bug@gnu.org \
--cc=rms@gnu.org \
--cc=sdl.web@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.