Kai.Grossjohann(a)CS.Uni-Dortmund.DE (Kai writes:
> Is it correct to say that you want to call (read
(current-buffer))
> and have it return (foo bar -1)?
Well, "want to" might be a slight exaggeration ;-)
Why?
In my copy of Emacs, I see the following:
/----
| *** Welcome to IELM *** Type (describe-mode) for help.
| ELISP> (read "(foo bar 1927120979049047309282389079128346218936)")
| (foo bar -1)
\----
Truncating large numbers into -1 looks like a bug to me, albeit a
convenient one in this case.
Also, the particular context is the Tramp handler for
file-attributes. It is supposed to return the user and group ids as
numbers. One user was reporting that he got a too-large number on
some remote host. I have some Perl code that gets executed on the
remote host and more or less directly prints the return value of
file-attributes. Tramp just `read's it from a temp buffer and
returns it.
[...]
FWIW, Richard is suggesting that I return the too-large user and
group ids as strings instead of numbers.
Richard is right. That's what I would do. Another way is to slap a
.0 and turn them into floating point. How well that works for you
depends on the range of numbers you have to be able to handle.
And `read' already does that in Emacs, so I don't have to do
any
additional work.
No additional work, but only depending on whether you want to support
XEmacs or not. I'm convinced that throwing an exception in face of
overflowing input is better than silent truncation. And even if it
weren't, it is my understanding that you want to support the current
versions of XEmacs.
> Your suggestion to trap the overflow and re-try seems to work,
but
> requires modifying the buffer.
Well, it's a temp buffer to begin with, so modifying the buffer is
not a problem. But I didn't get it to "work".
Here's a version that works (for me):
(defun read-ignoring-overflow ()
(let ((done nil)
(startpos (point))
result)
(while (not done)
(setq done t)
(condition-case err
(setq result (read (current-buffer)))
(invalid-read-syntax
(message "%s" err)
(unless (string-match "integer constant overflow" (cadr err))
;; If this is not an overflow error, resignal it.
(signal (car err) (cdr err)))
(setq done nil)
;; Replace the sexp before point with -1 and retry.
(kill-sexp -1)
(insert "-1")
(goto-char startpos))))
result))
Maybe I was just looking at the wrong spot. I kind of expected
point to advance to the trouble spot when reading from the buffer,
so it would have been easy to modify the right spot in the buffer.
But point didn't move.
The point moves for me, to the position right after the trouble spot.
But relying on that is usually not a good idea, which is why the
solution with continuable errors is the correct one. It's a shame we
can't use it.
> One interesting feature that XEmacs supports are continuable
errors.
Nice. But that will only work in a future XEmacs. If you have a
suggestion that will work with current XEmacs versions, that'd be
even greater.
See if the above works on the XEmacs you have. I think it should work
on XEmacsen since at least 19.12.
FWIW, Richard is suggesting that I return the too-large user and
group ids as strings instead of numbers. But the device number is
already returned as a cons if it is too large, and I'm not sure it's
a good idea to have two different solutions for the same problem in
the (interface to) same function. So I'm trying to convince him to
adopt the cons approach.
I wonder what you folks think about this: if the user or group id is
too large to represented as an int, what should a filename handler
return?
Please let's not go the cons route one more time -- it's a gross hack.
Use either floating point (if you're sure it won't overflow as well)
or a string. I'd use a string.