Prune most-positive-fixnum from Lisp source

I looked through all instances of most-negative-fixnum
and most-positive-fixnum in the Lisp source code, and
when it was easy I removed assumptions that integers
fit in fixnums.  The remaining instances are either
nontrivial to fix, or are inherent to the algorithm.
* lisp/arc-mode.el (archive-l-e): Do not convert to float,
since we have bignums now.  All uses changed.
* lisp/calc/calc.el (math-bignum):
Don’t special-case most-negative-fixnum.
* lisp/calendar/parse-time.el (parse-time-string):
* lisp/emacs-lisp/edebug.el (edebug-read-special):
* lisp/emacs-lisp/package.el (package--remove-hidden):
* lisp/gnus/nnfolder.el (nnfolder-read-folder):
* lisp/international/mule-util.el (filepos-to-bufferpos--dos):
* lisp/menu-bar.el (menu-bar-update-buffers):
* lisp/net/rcirc.el (rcirc-handler-317):
* lisp/org/org-agenda.el (org-cmp-ts):
* lisp/window.el (window--resize-child-windows):
Avoid arbitrary limit to most-positive-fixnum or to
most-negative-fixnum.
* lisp/calendar/time-date.el (days-to-time):
* lisp/erc/erc-dcc.el (erc-unpack-int):
Don’t worry about integer overflow.
* lisp/cedet/semantic/wisent/comp.el (wisent-BITS-PER-WORD):
* lisp/gnus/message.el (message-unique-id):
* lisp/org/org-footnote.el (org-footnote-new):
Simplify.
* lisp/erc/erc-dcc.el (erc-most-positive-int-bytes)
(erc-most-positive-int-msb): Remove; no longer needed.
* lisp/net/imap.el (imap-string-to-integer): Remove; unused.
* lisp/org/org-element.el (org-element--cache-generate-key):
Document fixnum limitation.
This commit is contained in:
Paul Eggert 2018-08-22 20:45:47 -07:00
parent ee641b87cf
commit a4a3c92e9d
18 changed files with 55 additions and 124 deletions

View file

@ -531,12 +531,10 @@ Each descriptor is a vector of the form
(defsubst archive-name (suffix)
(intern (concat "archive-" (symbol-name archive-subtype) "-" suffix)))
(defun archive-l-e (str &optional len float)
(defun archive-l-e (str &optional len)
"Convert little endian string/vector STR to integer.
Alternatively, STR may be a buffer position in the current buffer
in which case a second argument, length LEN, should be supplied.
FLOAT, if non-nil, means generate and return a float instead of an integer
\(use this for numbers that can overflow the Emacs integer)."
in which case a second argument, length LEN, should be supplied."
(if (stringp str)
(setq len (length str))
(setq str (buffer-substring str (+ str len))))
@ -545,7 +543,7 @@ FLOAT, if non-nil, means generate and return a float instead of an integer
(i 0))
(while (< i len)
(setq i (1+ i)
result (+ (if float (* result 256.0) (ash result 8))
result (+ (ash result 8)
(aref str (- len i)))))
result))
@ -1501,14 +1499,13 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
(fnlen (or (string-match "\0" namefld) 13))
(efnname (decode-coding-string (substring namefld 0 fnlen)
archive-file-name-coding-system))
;; Convert to float to avoid overflow for very large files.
(csize (archive-l-e (+ p 15) 4 'float))
(csize (archive-l-e (+ p 15) 4))
(moddate (archive-l-e (+ p 19) 2))
(modtime (archive-l-e (+ p 21) 2))
(ucsize (archive-l-e (+ p 25) 4 'float))
(ucsize (archive-l-e (+ p 25) 4))
(fiddle (string= efnname (upcase efnname)))
(ifnname (if fiddle (downcase efnname) efnname))
(text (format " %8.0f %-11s %-8s %s"
(text (format " %8d %-11s %-8s %s"
ucsize
(archive-dosdate moddate)
(archive-dostime modtime)
@ -1521,11 +1518,7 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
visual)
files (cons (vector efnname ifnname fiddle nil (1- p))
files)
;; p needs to stay an integer, since we use it in char-after
;; above. Passing through `round' limits the compressed size
;; to most-positive-fixnum, but if the compressed size exceeds
;; that, we cannot visit the archive anyway.
p (+ p 29 (round csize)))))
p (+ p 29 csize))))
(goto-char (point-min))
(let ((dash (concat "- -------- ----------- -------- "
(make-string maxlen ?-)
@ -1534,7 +1527,7 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
dash)
(archive-summarize-files (nreverse visual))
(insert dash
(format " %8.0f %d file%s"
(format " %8d %d file%s"
totalsize
(length files)
(if (= 1 (length files)) "" "s"))
@ -1567,10 +1560,9 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
(while (progn (goto-char p) ;beginning of a base header.
(looking-at "\\(.\\|\n\\)\\(.\\|\n\\)-l[hz][0-9ds]-"))
(let* ((hsize (byte-after p)) ;size of the base header (level 0 and 1)
;; Convert to float to avoid overflow for very large files.
(csize (archive-l-e (+ p 7) 4 'float)) ;size of a compressed file to follow (level 0 and 2),
(csize (archive-l-e (+ p 7) 4)) ;size of a compressed file to follow (level 0 and 2),
;size of extended headers + the compressed file to follow (level 1).
(ucsize (archive-l-e (+ p 11) 4 'float)) ;size of an uncompressed file.
(ucsize (archive-l-e (+ p 11) 4)) ;size of an uncompressed file.
(time1 (archive-l-e (+ p 15) 2)) ;date/time (MSDOS format in level 0, 1 headers
(time2 (archive-l-e (+ p 17) 2)) ;and UNIX format in level 2 header.)
(hdrlvl (byte-after (+ p 20))) ;header level
@ -1660,12 +1652,12 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
(archive-unixtime time1 time2)
(archive-dostime time1)))
(setq text (if archive-alternate-display
(format " %8.0f %5S %5S %s"
(format " %8d %5S %5S %s"
ucsize
(or uid "?")
(or gid "?")
ifnname)
(format " %10s %8.0f %-11s %-8s %s"
(format " %10s %8d %-11s %-8s %s"
modestr
ucsize
moddate
@ -1680,13 +1672,9 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
files (cons (vector prname ifnname fiddle mode (1- p))
files))
(cond ((= hdrlvl 1)
;; p needs to stay an integer, since we use it in goto-char
;; above. Passing through `round' limits the compressed size
;; to most-positive-fixnum, but if the compressed size exceeds
;; that, we cannot visit the archive anyway.
(setq p (+ p hsize 2 (round csize))))
(setq p (+ p hsize 2 csize)))
((or (= hdrlvl 2) (= hdrlvl 0))
(setq p (+ p thsize 2 (round csize)))))
(setq p (+ p thsize 2 csize))))
))
(goto-char (point-min))
(let ((dash (concat (if archive-alternate-display
@ -1824,32 +1812,21 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
;;
;; First, find the Zip64 end-of-central-directory locator.
(search-backward "PK\006\007")
;; Pay attention: the offset of Zip64 end-of-central-directory
;; is a 64-bit field, so it could overflow the Emacs integer
;; even on a 64-bit host, let alone 32-bit one. But since we've
;; already read the zip file into a buffer, and this is a byte
;; offset into the file we've read, it must be short enough, so
;; such an overflow can never happen, and we can safely read
;; these 8 bytes into an Emacs integer. Moreover, on host with
;; 32-bit Emacs integer we can only read 4 bytes, since they are
;; stored in little-endian byte order.
(setq emacs-int-has-32bits (<= most-positive-fixnum #x1fffffff))
(setq p (+ (point-min)
(archive-l-e (+ (point) 8) (if emacs-int-has-32bits 4 8))))
(archive-l-e (+ (point) 8) 8)))
(goto-char p)
;; We should be at Zip64 end-of-central-directory record now.
(or (string= "PK\006\006" (buffer-substring p (+ p 4)))
(error "Unrecognized ZIP file format"))
;; Offset to central directory:
(setq p (archive-l-e (+ p 48) (if emacs-int-has-32bits 4 8))))
(setq p (archive-l-e (+ p 48) 8)))
(setq p (+ p (point-min)))
(while (string= "PK\001\002" (buffer-substring p (+ p 4)))
(let* ((creator (byte-after (+ p 5)))
;; (method (archive-l-e (+ p 10) 2))
(modtime (archive-l-e (+ p 12) 2))
(moddate (archive-l-e (+ p 14) 2))
;; Convert to float to avoid overflow for very large files.
(ucsize (archive-l-e (+ p 24) 4 'float))
(ucsize (archive-l-e (+ p 24) 4))
(fnlen (archive-l-e (+ p 28) 2))
(exlen (archive-l-e (+ p 30) 2))
(fclen (archive-l-e (+ p 32) 2))
@ -1874,7 +1851,7 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
(string= (upcase efnname) efnname)))
(ifnname (if fiddle (downcase efnname) efnname))
(width (string-width ifnname))
(text (format " %10s %8.0f %-11s %-8s %s"
(text (format " %10s %8d %-11s %-8s %s"
modestr
ucsize
(archive-dosdate moddate)
@ -1900,7 +1877,7 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
dash)
(archive-summarize-files (nreverse visual))
(insert dash
(format " %8.0f %d file%s"
(format " %8d %d file%s"
totalsize
(length files)
(if (= 1 (length files)) "" "s"))
@ -1971,8 +1948,7 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
(let* ((next (1+ (archive-l-e (+ p 6) 4)))
(moddate (archive-l-e (+ p 14) 2))
(modtime (archive-l-e (+ p 16) 2))
;; Convert to float to avoid overflow for very large files.
(ucsize (archive-l-e (+ p 20) 4 'float))
(ucsize (archive-l-e (+ p 20) 4))
(namefld (buffer-substring (+ p 38) (+ p 38 13)))
(dirtype (byte-after (+ p 4)))
(lfnlen (if (= dirtype 2) (byte-after (+ p 56)) 0))
@ -1995,7 +1971,7 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
(fiddle (and (= lfnlen 0) (string= efnname (upcase efnname))))
(ifnname (if fiddle (downcase efnname) efnname))
(width (string-width ifnname))
(text (format " %8.0f %-11s %-8s %s"
(text (format " %8d %-11s %-8s %s"
ucsize
(archive-dosdate moddate)
(archive-dostime modtime)
@ -2017,7 +1993,7 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
dash)
(archive-summarize-files (nreverse visual))
(insert dash
(format " %8.0f %d file%s"
(format " %8d %d file%s"
totalsize
(length files)
(if (= 1 (length files)) "" "s"))
@ -2211,8 +2187,6 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
(while (looking-at archive-ar-file-header-re)
(let ((name (match-string 1))
extname
;; Emacs will automatically use float here because those
;; timestamps don't fit in our ints.
(time (string-to-number (match-string 2)))
(user (match-string 3))
(group (match-string 4))

View file

@ -2781,13 +2781,6 @@ largest Emacs integer.")
(cond
((>= a 0)
(cons 'bigpos (math-bignum-big a)))
((= a most-negative-fixnum)
;; Note: cannot get the negation directly because
;; (- most-negative-fixnum) is most-negative-fixnum.
;;
;; most-negative-fixnum := -most-positive-fixnum - 1
(math-sub (cons 'bigneg (math-bignum-big most-positive-fixnum))
1))
(t
(cons 'bigneg (math-bignum-big (- a))))))

View file

@ -98,7 +98,7 @@ letters, digits, plus or minus signs or colons."
`(((6) parse-time-weekdays)
((3) (1 31))
((4) parse-time-months)
((5) (100 ,most-positive-fixnum))
((5) (100))
((2 1 0)
,#'(lambda () (and (stringp parse-time-elt)
(= (length parse-time-elt) 8)
@ -170,7 +170,9 @@ any values that are unknown are returned as nil."
'lambda)))
(and (numberp parse-time-elt)
(<= (car predicate) parse-time-elt)
(<= parse-time-elt (cadr predicate))
(or (not (cdr predicate))
(<= parse-time-elt
(cadr predicate)))
parse-time-elt))
((symbolp predicate)
(cdr (assoc parse-time-elt

View file

@ -175,8 +175,7 @@ If DATE lacks timezone information, GMT is assumed."
;;;###autoload
(defun days-to-time (days)
"Convert DAYS into a time value."
(let ((time (condition-case nil (seconds-to-time (* 86400.0 days))
(range-error (list most-positive-fixnum 65535)))))
(let ((time (seconds-to-time (* 86400 days))))
(if (integerp days)
(setcdr (cdr time) nil))
time))
@ -277,9 +276,7 @@ return something of the form \"001 year\".
The \"%z\" specifier does not print anything. When it is used, specifiers
must be given in order of decreasing size. To the left of \"%z\", nothing
is output until the first non-zero unit is encountered.
This function does not work for SECONDS greater than `most-positive-fixnum'."
is output until the first non-zero unit is encountered."
(let ((start 0)
(units '(("y" "year" 31536000)
("d" "day" 86400)

View file

@ -139,14 +139,7 @@ If optional LEFT is non-nil insert spaces on left."
;;;; Environment dependencies
;;;; ------------------------
(defconst wisent-BITS-PER-WORD
(let ((i 1)
(do-shift (if (boundp 'most-positive-fixnum)
(lambda (i) (ash most-positive-fixnum (- i)))
(lambda (i) (ash 1 i)))))
(while (not (zerop (funcall do-shift i)))
(setq i (1+ i)))
i))
(defconst wisent-BITS-PER-WORD (logcount most-positive-fixnum))
(defsubst wisent-WORDSIZE (n)
"(N + BITS-PER-WORD - 1) / BITS-PER-WORD."

View file

@ -894,8 +894,7 @@ circular objects. Let `read' read everything else."
(while (and (>= (following-char) ?0) (<= (following-char) ?9))
(forward-char 1))
(let ((n (string-to-number (buffer-substring start (point)))))
(when (and read-circle
(<= n most-positive-fixnum))
(when read-circle
(cond
((eq ?= (following-char))
;; Make a placeholder for #n# to use temporarily.
@ -910,7 +909,7 @@ circular objects. Let `read' read everything else."
(throw 'return (setf (cdr elem) obj)))))
((eq ?# (following-char))
;; #n# returns a previously read object.
(let ((elem (assq n edebug-read-objects)))
(let ((elem (assoc n edebug-read-objects)))
(when (consp elem)
(forward-char 1)
(throw 'return (cdr elem))))))))))

View file

@ -2673,12 +2673,11 @@ to their archives."
((not package-menu-hide-low-priority)
pkg-list)
((eq package-menu-hide-low-priority 'archive)
(let* ((max-priority most-negative-fixnum)
(out))
(let (max-priority out)
(while pkg-list
(let ((p (pop pkg-list)))
(let ((priority (package-desc-priority p)))
(if (< priority max-priority)
(if (and max-priority (< priority max-priority))
(setq pkg-list nil)
(push p out)
(setq max-priority priority)))))

View file

@ -224,14 +224,6 @@ which is big-endian."
(setq i (1- i)))
str))
(defconst erc-most-positive-int-bytes
(ceiling (/ (ceiling (/ (log most-positive-fixnum) (log 2))) 8.0))
"Maximum number of bytes for a fixnum.")
(defconst erc-most-positive-int-msb
(ash most-positive-fixnum (- 0 (* 8 (1- erc-most-positive-int-bytes))))
"Content of the most significant byte of most-positive-fixnum.")
(defun erc-unpack-int (str)
"Unpack a packed string into an integer."
(let ((len (length str)))
@ -242,11 +234,6 @@ which is big-endian."
(when (> start 0)
(setq str (substring str start))
(setq len (- len start))))
;; make sure size is not larger than Emacs can handle
(when (or (> len (min 4 erc-most-positive-int-bytes))
(and (eq len erc-most-positive-int-bytes)
(> (aref str 0) erc-most-positive-int-msb)))
(error "ERC-DCC (erc-unpack-int): packet to send is too large"))
;; unpack
(let ((num 0)
(count 0))

View file

@ -5564,7 +5564,7 @@ In posting styles use `(\"Expires\" (make-expires-date 30))'."
;; Instead we use this randomly inited counter.
(setq message-unique-id-char
(% (1+ (or message-unique-id-char
(logand (random most-positive-fixnum) (1- (ash 1 20)))))
(random (ash 1 20))))
;; (current-time) returns 16-bit ints,
;; and 2^16*25 just fits into 4 digits i base 36.
(* 25 25)))

View file

@ -883,11 +883,11 @@ deleted. Point is left where the deleted region was."
(active (or (cadr (assoc group nnfolder-group-alist))
(cons 1 0)))
(scantime (assoc group nnfolder-scantime-alist))
(minid most-positive-fixnum)
(minid (cdr active))
maxid start end newscantime
novbuf articles newnum
buffer-read-only)
(setq maxid (cdr active))
(setq maxid minid)
(unless (or gnus-nov-is-evil nnfolder-nov-is-evil
(and (file-exists-p nov)

View file

@ -342,7 +342,7 @@ per-character basis, this may not be accurate."
(let ((eol-offset 0)
;; Make sure we terminate, even if BYTE falls right in the middle
;; of a CRLF or some other weird corner case.
(omin 0) (omax most-positive-fixnum)
(omin 0) omax
pos lines)
(while
(progn
@ -355,9 +355,9 @@ per-character basis, this may not be accurate."
(setq pos (point-max))))
;; Adjust POS for DOS EOL format.
(setq lines (1- (line-number-at-pos pos)))
(and (not (= lines eol-offset)) (> omax omin)))
(and (not (= lines eol-offset)) (or (not omax) (> omax omin))))
(if (> lines eol-offset)
(setq omax (min (1- omax) lines)
(setq omax (if omax (min (1- omax) lines) lines)
eol-offset omax)
(setq omin (max (1+ omin) lines)
eol-offset omin)))

View file

@ -2135,9 +2135,9 @@ It must accept a buffer as its only required argument.")
;; Make the menu of buffers proper.
(setq buffers-menu
(let ((i 0)
(limit (if (and (integerp buffers-menu-max-size)
(> buffers-menu-max-size 1))
buffers-menu-max-size most-positive-fixnum))
(limit (and (integerp buffers-menu-max-size)
(> buffers-menu-max-size 1)
buffers-menu-max-size))
alist)
;; Put into each element of buffer-list
;; the name for actual display,
@ -2161,7 +2161,7 @@ It must accept a buffer as its only required argument.")
alist)
;; If requested, list only the N most recently
;; selected buffers.
(when (= limit (setq i (1+ i)))
(when (eql limit (setq i (1+ i)))
(setq buffers nil)))))
(list (menu-bar-buffer-vector alist))))

View file

@ -1696,18 +1696,6 @@ MAILBOX specifies a mailbox on the server in BUFFER."
(concat "UID STORE " articles
" +FLAGS" (if silent ".SILENT") " (" flags ")"))))))
;; Cf. http://thread.gmane.org/gmane.emacs.gnus.general/65317/focus=65343
;; Signal an error if we'd get an integer overflow.
;;
;; FIXME: Identify relevant calls to `string-to-number' and replace them with
;; `imap-string-to-integer'.
(defun imap-string-to-integer (string &optional base)
(let ((number (string-to-number string base)))
(if (> number most-positive-fixnum)
(error
(format "String %s cannot be converted to a Lisp integer" number))
number)))
(defun imap-fetch-safe (uids props &optional receive nouidfetch buffer)
"Like `imap-fetch', but DTRT with Exchange 2007 bug.
However, UIDS here is a cons, where the car is the canonical form

View file

@ -2787,10 +2787,7 @@ the only argument."
"RPL_WHOISIDLE"
(let* ((nick (nth 1 args))
(idle-secs (string-to-number (nth 2 args)))
(idle-string
(if (< idle-secs most-positive-fixnum)
(format-seconds "%yy %dd %hh %mm %z%ss" idle-secs)
"a very long time"))
(idle-string (format-seconds "%yy %dd %hh %mm %z%ss" idle-secs))
(signon-time (seconds-to-time (string-to-number (nth 3 args))))
(signon-string (format-time-string "%c" signon-time))
(message (format "%s idle for %s, signed on %s"

View file

@ -7009,15 +7009,15 @@ When TYPE is \"scheduled\", \"deadline\", \"timestamp\" or
\"timestamp_ia\", compare within each of these type. When TYPE
is the empty string, compare all timestamps without respect of
their type."
(let* ((def (if org-sort-agenda-notime-is-late most-positive-fixnum -1))
(let* ((def (and (not org-sort-agenda-notime-is-late) -1))
(ta (or (and (string-match type (or (get-text-property 1 'type a) ""))
(get-text-property 1 'ts-date a))
def))
(tb (or (and (string-match type (or (get-text-property 1 'type b) ""))
(get-text-property 1 'ts-date b))
def)))
(cond ((< ta tb) -1)
((< tb ta) +1))))
(cond ((if ta (and tb (< ta tb)) tb) -1)
((if tb (and ta (< tb ta)) ta) +1))))
(defsubst org-cmp-habit-p (a b)
"Compare the todo states of strings A and B."

View file

@ -4856,7 +4856,7 @@ table is cleared once the synchronization is complete."
(defun org-element--cache-generate-key (lower upper)
"Generate a key between LOWER and UPPER.
LOWER and UPPER are integers or lists, possibly empty.
LOWER and UPPER are fixnums or lists of same, possibly empty.
If LOWER and UPPER are equals, return LOWER. Otherwise, return
a unique key, as an integer or a list of integers, according to

View file

@ -636,7 +636,7 @@ or new, let the user edit the definition of the footnote."
(let* ((all (org-footnote-all-labels))
(label
(if (eq org-footnote-auto-label 'random)
(format "%x" (random most-positive-fixnum))
(format "%x" (abs (random)))
(org-footnote-normalize-label
(let ((propose (org-footnote-unique-label all)))
(if (eq org-footnote-auto-label t) propose

View file

@ -3084,11 +3084,12 @@ already set by this routine."
(while (and best-window (not (zerop delta)))
(setq sub last)
(setq best-window nil)
(setq best-value most-negative-fixnum)
(setq best-value nil)
(while sub
(when (and (consp (window-new-normal sub))
(not (<= (car (window-new-normal sub)) 0))
(> (cdr (window-new-normal sub)) best-value))
(or (not best-value)
(> (cdr (window-new-normal sub)) best-value)))
(setq best-window sub)
(setq best-value (cdr (window-new-normal sub))))
@ -3113,10 +3114,11 @@ already set by this routine."
(while (and best-window (not (zerop delta)))
(setq sub last)
(setq best-window nil)
(setq best-value most-positive-fixnum)
(setq best-value nil)
(while sub
(when (and (numberp (window-new-normal sub))
(< (window-new-normal sub) best-value))
(or (not best-value)
(< (window-new-normal sub) best-value)))
(setq best-window sub)
(setq best-value (window-new-normal sub)))