** Other process information
-*** Non-ASCII characters in Emacs files
-
-If you introduce non-ASCII characters into Emacs source files, it is a
-good idea to add a 'coding' cookie to the file to state its encoding.
-Please use the UTF-8 encoding unless it cannot do the job for some
-good reason. As of Emacs 24.4, it is no longer necessary to have
-explicit 'coding' cookies in *.el files if they are encoded in UTF-8,
-but other files need them even if encoded in UTF-8. However, if
-an *.el file is intended for use with older Emacs versions (e.g. if
-it's also distributed via ELPA), having an explicit encoding
-specification is still a good idea.
-
-*** Useful files in the admin/ directory
-
-See all the files in admin/notes/* . In particular, see
-admin/notes/newfile, see admin/notes/repo.
-
-The file admin/MAINTAINERS records the areas of interest of frequent
-Emacs contributors. If you are making changes in one of the files
-mentioned there, it is a good idea to consult the person who expressed
-an interest in that file, and/or get his/her feedback for the changes.
-If you are a frequent contributor and have interest in maintaining
-specific files, please record those interests in that file, so that
-others could be aware of that.
-
-*** git vs rename
-
-Git does not explicitly represent a file renaming; it uses a percent
-changed heuristic to deduce that a file was renamed. So if you are
-planning to make extensive changes to a file after renaming it (or
-moving it to another directory), you should:
-
-- create a feature branch
-
-- commit the rename without any changes
-
-- make other changes
-
-- merge the feature branch to trunk, _not_ squashing the commits into
- one. The commit message on this merge should summarize the renames
- and all the changes.
-
** Emacs Mailing lists.
Discussion about Emacs development takes place on emacs-devel@gnu.org.
such patch without additional remarks, you can use a command like
'git send-email --to=bug-gnu-emacs@gnu.org 0001-DESCRIPTION.patch'.
+** Issue tracker (a.k.a. "bug tracker")
+
+The Emacs issue tracker is at http://debbugs.gnu.org/. The form
+presented by that page allows to view bug reports and search the
+database for bugs matching several criteria. Messages posted to the
+bug-gnu-emacs@gnu.org mailing list, mentioned above, are recorded by
+the tracker with the corresponding bugs/issues.
+
+GNU ELPA has a 'debbugs' package that allows accessing the tracker
+database from Emacs.
+
** Document your changes.
Any change that matters to end-users should have an entry in etc/NEWS.
The file etc/DEBUG describes how to debug Emacs bugs.
+*** Non-ASCII characters in Emacs files
+
+If you introduce non-ASCII characters into Emacs source files, it is a
+good idea to add a 'coding' cookie to the file to state its encoding.
+Please use the UTF-8 encoding unless it cannot do the job for some
+good reason. As of Emacs 24.4, it is no longer necessary to have
+explicit 'coding' cookies in *.el files if they are encoded in UTF-8,
+but other files need them even if encoded in UTF-8. However, if
+an *.el file is intended for use with older Emacs versions (e.g. if
+it's also distributed via ELPA), having an explicit encoding
+specification is still a good idea.
+
+*** Useful files in the admin/ directory
+
+See all the files in admin/notes/* . In particular, see
+admin/notes/newfile, see admin/notes/repo.
+
+The file admin/MAINTAINERS records the areas of interest of frequent
+Emacs contributors. If you are making changes in one of the files
+mentioned there, it is a good idea to consult the person who expressed
+an interest in that file, and/or get his/her feedback for the changes.
+If you are a frequent contributor and have interest in maintaining
+specific files, please record those interests in that file, so that
+others could be aware of that.
+
+*** git vs rename
+
+Git does not explicitly represent a file renaming; it uses a percent
+changed heuristic to deduce that a file was renamed. So if you are
+planning to make extensive changes to a file after renaming it (or
+moving it to another directory), you should:
+
+- create a feature branch
+
+- commit the rename without any changes
+
+- make other changes
+
+- merge the feature branch to trunk, _not_ squashing the commits into
+ one. The commit message on this merge should summarize the renames
+ and all the changes.
+
\f
This file is part of GNU Emacs.
+2015-11-08 Paul Eggert <eggert@cs.ucla.edu>
+
+ Prefer xpalloc to doubling buffers by hand
+
+ * src/lread.c (grow_read_buffer): New function, which uses xpalloc.
+ (read1): Use it for simplicity.
+ * src/macros.c (store_kbd_macro_char):
+ * src/minibuf.c (read_minibuf_noninteractive):
+ * src/term.c (encode_terminal_code):
+ * src/xrdb.c (magic_db):
+ Prefer xpalloc to growing buffers by hand.
+ This doesn’t fix any bugs, but simplifies the code a bit.
+
+2015-11-08 Paul Eggert <eggert@cs.ucla.edu>
+
+ Merge from gnulib
+
+ This incorporates:
+ 2015-11-05 timespec-sub: fix overflow bug; add tests
+ 2015-11-04 intprops: revise _WRAPV macros, revert _OVERFLOW
+ 2015-11-03 intprops: add parentheses
+ * lib/intprops.h, lib/timespec-add.c, lib/timespec-sub.c:
+ Copy from gnulib.
+
+2015-11-07 David Reitter <david.reitter@gmail.com>
+
+ Provide NS notification objects where required to eliminate warnings
+
+ * nsterm.m (windowDidResize:, toggleFullScreen:):
+ Call notification functions with notification objects
+ as per delegate APIs.
+
+2015-11-07 Noam Postavsky <npostavs@users.sourceforge.net>
+
+ Add test for bug #21824
+
+ * test/automated/buffer-tests.el: New file.
+ (overlay-modification-hooks-message-other-buf): New test.
+
+2015-11-07 Kelvin White <kwhite@gnu.org>
+
+ * lisp/erc/erc-pcomplete.el (pcomplete-erc-nicks): Fix bug#18771.
+
+2015-11-07 David Reitter <david.reitter@gmail.com>
+
+ Ignore fullscreen exit notifications on NS when frame is dead
+
+ * nsterm.m (windowDidResize:, windowWillExitFullScreen:)
+ (windowDidExitFullScreen:): Return if frame is dead.
+ These functions may be called when a fullscreen frame
+ is closed; they are called before, not after.
+
+ May address Bug#21428.
+
+2015-11-07 Eli Zaretskii <eliz@gnu.org>
+
+ Speed up lookup in redisplay--variables
+
+ * lisp/frame.el (redisplay--variables): Make it a hash-table.
+
+ * src/xdisp.c (maybe_set_redisplay): Access redisplay--variables
+ as a hash-table. This speeds up this function by an order of
+ magnitude: where previously a setq was slowed down by 100% by
+ introducing the maybe_set_redisplay test, it is now only 5%
+ slower.
+ (syms_of_xdisp) <redisplay--variables>: Doc fix.
+
+2015-11-07 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * lisp/emacs-lisp/cl-macs.el (cl-defstruct): Fix a bug.
+
+ The defsubst was being created as:
+ (cl-defsubst name (args) ("DOC") ...)
+
+ * test/automated/cl-lib-tests.el (cl-lib-struct-constructors):
+ Add test.
+
+2015-11-07 Mihai Olteanu <mihai_olteanu@fastmail.fm> (tiny change)
+
+ Update doc string of hexl-mode
+
+ * lisp/hexl.el (hexl-mode): Doc fix. (Bug#21800)
+
+2015-11-07 Eli Zaretskii <eliz@gnu.org>
+
+ Fix error in copy-abbrev-table
+
+ * lisp/abbrev.el (define-abbrev): Don't erase the :abbrev-table-modiff
+ property of the abbrev-table. (Bug#21828)
+
+ * test/automated/abbrev-tests.el: New file.
+
+2015-11-07 Michael Albinus <michael.albinus@gmx.de>
+
+ Add test to auto-revert-tests.el for Bug#21841
+
+ * test/automated/auto-revert-tests.el
+ (auto-revert-test01-auto-revert-several-files): New test.
+ (auto-revert-test02-auto-revert-tail-mode)
+ (auto-revert-test03-auto-revert-mode-dired): Rename them.
+
+2015-11-07 Martin Rudalics <rudalics@gmx.at>
+
+ * doc/lispref/windows.texi (Coordinates and Windows): Fix typo.
+
+2015-11-07 Martin Rudalics <rudalics@gmx.at>
+
+ In x_consider_frame_title don't set title of tooltip frames
+
+ * src/xdisp.c (x_consider_frame_title): Return immediately for
+ tooltip frames to avoid displaying empty tooltips.
+
+2015-11-06 Anders Lindgren <andlind@gmail.com>
+
+ Fixed NextStep fullscreen problem (bug#21770).
+
+ * src/nsterm.m (ns_constrain_all_frames): Don't constrain
+ fullscreen frames.
+
+2015-11-06 Eli Zaretskii <eliz@gnu.org>
+
+ Ensure redisplay after evaluation
+
+ * lisp/progmodes/elisp-mode.el (elisp--eval-last-sexp):
+ Revert last change.
+ * lisp/frame.el (redisplay--variables): Populate the
+ redisplay--variables list.
+ * src/xdisp.c (maybe_set_redisplay): New function.
+ (syms_of_xdisp) <redisplay--variables>: New variable.
+ * src/window.h (maybe_set_redisplay): Declare prototype.
+ * src/data.c (set_internal): Call maybe_set_redisplay. (Bug#21835)
+
+2015-11-06 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * test/automated/subr-tests.el (subr-test-when): Fix again.
+
+2015-11-06 Eli Zaretskii <eliz@gnu.org>
+
+ Don't invoke overlay modification hooks in wrong buffer
+
+ * src/buffer.c (report_overlay_modification): When called with
+ AFTER non-zero, don't invoke overlay modification hooks if the
+ buffer recorded in last_overlay_modification_hooks is different
+ from the current buffer. (Bug#21824)
+
+2015-11-06 Juanma Barranquero <lekktu@gmail.com>
+
+ * admin/notes/repo: Fix a few obsolete references to Bazaar.
+
+2015-11-06 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * test/automated/subr-tests.el (subr-test-when): Fix test.
+
+2015-11-06 Martin Rudalics <rudalics@gmx.at>
+
+ Avoid division by zero crash observed by Yuan MEI
+
+ See http://lists.gnu.org/archive/html/emacs-devel/2015-11/msg00194.html.
+
+ * src/dispnew.c (required_matrix_height, required_matrix_width):
+ Avoid division by zero.
+ * src/xterm.c (x_term_init): Init dpyinfo->smallest_font_height and
+ dpyinfo->smallest_char_width to 1.
+
+2015-11-06 Eli Zaretskii <eliz@gnu.org>
+
+ Ensure redisplay after "C-x C-e"
+
+ * lisp/progmodes/elisp-mode.el (elisp--eval-last-sexp): Make sure
+ redisplay happens to account for any side effects of the evaluated
+ sexp. (Bug#21835)
+
+2015-11-06 Michael Albinus <michael.albinus@gmx.de>
+
+ Skip some file notification tests for cygwin
+
+ * test/automated/file-notify-tests.el (file-notify--test-with-events):
+ Remove argument TIMEOUT. Adapt all callees.
+ (file-notify-test02-events, file-notify-test04-file-validity):
+ Skip for cygwin. (Bug#21804)
+
+2015-11-05 Stephen Leake <stephen_leake@stephe-leake.org>
+
+ * lisp/progmodes/xref.el: Require semantic/symref during compilation.
+
+2015-11-05 Daiki Ueno <ueno@gnu.org>
+
+ Suppress redundant Pinentry startup messages
+
+ * lisp/net/pinentry.el (pinentry-start): Add optional QUIET argument.
+ * lisp/epg.el: Declare `pinentry-start'.
+ (epg--start): Call `pinentry-start' with QUIET argument set.
+
+2015-11-05 Xue Fuqiao <xfq.free@gmail.com>
+
+ * doc/emacs/ack.texi (Acknowledgments): Updates.
+
+2015-11-05 Juanma Barranquero <lekktu@gmail.com>
+
+ * test/automated/elisp-mode-test.el: Silence some run-time warnings.
+ (xref-elisp-deftest): Bind `find-file-suppress-same-file-warnings' to t.
+
+2015-11-05 Tassilo Horn <tsdh@gnu.org>
+
+ * lisp/textmodes/tex-mode.el (tex--prettify-symbols-alist):
+ Add prettification support for \times.
+
+2015-11-05 Juanma Barranquero <lekktu@gmail.com>
+
+ * test/automated/process-tests.el: Skip tests when bash is unavailable.
+ (process-test-sentinel-accept-process-output)
+ (process-test-sentinel-sit-for): skip-unless bash executable found.
+
+2015-11-05 Eli Zaretskii <eliz@gnu.org>
+
+ Add test for bug #21831
+
+ * test/automated/process-tests.el
+ (start-process-should-not-modify-arguments): New test. (Bug#21831)
+ Suggested by Nicolas Richard <youngfrog@members.fsf.org>
+
+2015-11-04 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * lisp/emacs-lisp/eieio-compat.el: Typo caught by tests.
+
+ (eieio--generic-static-object-generalizer): Fix typo.
+ * test/automated/eieio-tests.el: Byte-compile it again. It looks
+ like the underlying cause of bug#17852 was fixed in the mean time.
+
+2015-11-04 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ Revert "* lisp/subr.el (when): Use `macroexp-progn'"
+
+ This reverts commit 8e843831eaf271801836b7a3e4dd3b4fb0bb72b8.
+ It breaks bootstrapping (duh).
+
+2015-11-04 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * lisp/files.el (report-errors): Obsolete.
+
+ (normal-mode, hack-local-variables, dir-locals-find-file):
+ Use `with-demoted-errors' instead.
+
+2015-11-04 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * lisp/subr.el (when): Use `macroexp-progn'.
+
+ * test/automated/subr-tests.el (subr-test-when): New test.
+
+2015-11-04 Juanma Barranquero <lekktu@gmail.com>
+
+ * lisp/progmodes/xref.el: Doc fixes.
+ (xref-make-file-location, xref-make-buffer-location, xref-make)
+ (xref-make-bogus-location, xref-make-match): Add cross-references.
+ (xref--insert-xrefs): Fix typo in docstring.
+
+2015-11-04 Anders Lindgren <andlind@gmail.com>
+
+ Render fringe bitmaps correctly on NextStep (bug#21301)
+
+ The fringe bitmaps were inverted, the background was not transparent,
+ the image data was horizontally mirrored, and periodic fringe bitmaps
+ were not supported.
+
+ * src/nsimage.m ([EmacsImage initFromXBM:width:height:fg:bg:]):
+ When both background and foreground colors are 0, set the background
+ alpha channel to 0 (making the background transparent). When
+ copying the image data, do this from the most significant bit
+ (leftmost) to the least (rightmost), to avoid mirroring.
+ * src/nsterm.m (ns_draw_fringe_bitmap): Don't invert the image bits.
+ Add support for periodic images (e.g. the empty line indicator).
+
+2015-11-03 Michael Heerdegen <michael_heerdegen@web.de>
+
+ * lisp/emacs-lisp/pcase.el (pcase): Tweak docstring.
+
+2015-11-03 Nicolas Petton <nicolas@petton.fr>
+
+ * admin/MAINTAINERS: Add seq-tests.el, map-tests.el, and thunk-tests.el.
+
+ * admin/MAINTAINERS: Add thunk.el.
+
+2015-11-03 Jay Belanger <jay.p.belanger@gmail.com>
+
+ * lisp/calc/calc (calc-bug-address): Change maintainer address.
+
+2015-11-03 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix a stupid error in gfilenotify.c
+
+ * src/gfilenotify.c (dir_monitor_callback): Cancel monitor only,
+ if we've got a `deleted' signal AND the file name is the watched one.
+
+2015-11-03 Stephen Leake <stephen_leake@stephe-leake.org>
+
+ Fix Bug#21816; case insensitive file system in elisp-mode-tests.el
+
+ * test/automated/elisp-mode-tests.el (xref-elisp-test-run):
+ Use case-insensitive string compare for file names.
+ (emacs-test-dir): Add 'downcase' to cause case differences (at
+ least on my system).
+
+2015-11-02 Juanma Barranquero <lekktu@gmail.com>
+
+ flymake-tests.el (warning-predicate-rx-gcc): Fix check
+
+ * test/automated/flymake-tests.el (warning-predicate-rx-gcc):
+ Also check that "make" is available, not just "gcc".
+
+2015-11-02 Ken Brown <kbrown@cornell.edu>
+
+ Document behavior of collation on Cygwin
+
+ * test/automated/fns-tests.el (fns-tests-collate-sort): Mark as
+ expected failure on Cygwin.
+ * doc/lispref/strings.texi (Text Comparison): Document that
+ punctuation and whitespace are not ignored for sorting on Cygwin.
+
+2015-11-02 Dani Moncayo <dmoncayo@gmail.com>
+
+ * build-aux/msys-to-w32: Prevent double slashes in w32 path list.
+
+2015-11-01 Glenn Morris <rgm@gnu.org>
+
+ * lisp/progmodes/f90.el (f90-no-block-limit): Add associate.
+ (Bug#21794)
+ * test/automated/f90.el (f90-test-bug21794): New test.
+
+2015-11-01 Juanma Barranquero <lekktu@gmail.com>
+
+ Fix incompatibility with TCC in test for bug#18745
+
+ * test/automated/process-tests.el (process-test-quoted-batfile):
+ Remove spaces unrelated to the bug being tested.
+
+2015-11-01 Michael Albinus <michael.albinus@gmx.de>
+
+ Improve completion in tramp-gvfs.el
+
+ * lisp/net/tramp-gvfs.el (tramp-zeroconf-parse-device-names):
+ Rename from `tramp-zeroconf-parse-service-device-names'.
+ (tramp-zeroconf-parse-webdav-device-names): Remove. Code merged
+ with `tramp-zeroconf-parse-device-names'.
+ (tramp-gvfs-parse-device-names): New defun.
+ (top): Use it when `tramp-zeroconf-parse-device-names' is not
+ applicable.
+
+ * lisp/net/tramp.el (tramp-set-completion-function): The argument
+ could also be a zeroconf service type.
+
2015-10-31 Thomas Fitzsimmons <fitzsim@fitzsim.org>
- ntlm.el: Change version to 2.0.0
+ * lisp/net/ntlm.el: Change version to 2.0.0.
2015-10-31 Juanma Barranquero <lekktu@gmail.com>
* lisp/net/soap-client.el, lisp/net/soap-inspect.el: Update home page.
+2015-10-25 Eli Zaretskii <eliz@gnu.org>
+
+ * lisp/progmodes/grep.el (grep): Doc fix. (Bug#21754)
+
+2015-10-25 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * src/keyboard.c (post-command-hook): Extend the docstring.
+ Mainly, explain how to use it without hanging Emacs, or giving the
+ impression that it is hanging. Also mention `pre-command-hook'.
+ (pre-command-hook): Mention `post-command-hook'.
+
+2015-10-25 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * lisp/custom.el (custom-declare-variable): Shorten code again.
+ Without using pcase this time. We can't use pcase because it is
+ loaded after custom in loadup.el. Also add a comment explaining
+ this to future dummies like me.
+
+2015-10-25 Michael Albinus <michael.albinus@gmx.de>
+
+ * doc/lispref/os.texi (File Notifications): Document `stopped event'.
+
+2015-10-25 Michael Albinus <michael.albinus@gmx.de>
+
+ Introduce `stopped' event in file notification
+
+ * lisp/filenotify.el (file-notify--rm-descriptor): New defun.
+ (file-notify-rm-watch): Use it.
+ (file-notify-callback): Implement `stopped' event.
+ (file-notify-add-watch): Mention `stopped' in the docstring.
+ Check, that upper directory exists.
+
+ * test/automated/file-notify-tests.el (file-notify-test01-add-watch):
+ Add two test cases.
+ (file-notify-test02-events): Handle also `stopped' event.
+ (file-notify-test04-file-validity): Add another test case.
+
+2015-10-25 Paul Eggert <eggert@cs.ucla.edu>
+
+ Revert commit that broke 'make bootstrap'
+
+ * lisp/custom.el (custom-declare-variable): Revert commit
+ 79fac080d277fed07b3c192890ad59d36d9f83b6. custom.el needs to work
+ even when pcase has not been defined yet, when doing bootstrapping.
+
+2015-10-25 Paul Eggert <eggert@cs.ucla.edu>
+
+ Port recent inline functions fix to Standard C
+
+ * src/lisp.h (LISP_MACRO_DEFUN, LISP_MACRO_DEFUN_VOID): Remove.
+ All uses rewritten to define the function directly rather than to
+ use a macro to define the function. This conforms to Standard C,
+ which does not allow stray semicolons at the top level. I hope it
+ also avoids the problems with TAGS. Those macros, though clever,
+ were pretty confusing anyway, and it wasn’t clear they were worth
+ the aggravation even without the TAGS problem.
+
+2015-10-24 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * lisp/isearch.el: Make character-fold search the default again.
+
+2015-10-24 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * lisp/character-fold.el: Many improvements.
+ (character-fold-search-forward, character-fold-search-backward):
+ New command.
+ (character-fold-to-regexp): Remove lax-whitespace hack.
+ (character-fold-search): Remove variable. Only isearch and
+ query-replace use char-folding, and they both have their own
+ variables to configure that.
+
+2015-10-24 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * lisp/isearch.el: Generalize definition of regexp-function toggles.
+ (isearch-specify-regexp-function): New macro for specifying
+ possible values of `isearch-regexp-function'.
+ (isearch-toggle-character-fold, isearch-toggle-symbol)
+ (isearch-toggle-word): Define with `isearch-specify-regexp-function'.
+
+2015-10-24 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * lisp/isearch.el (search-default-regexp-mode): New variable.
+ (isearch-mode): Use it.
+
+2015-10-24 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * lisp/isearch.el (search-exit-option, search-slow-window-lines)
+ (search-slow-speed, search-upper-case)
+ (search-nonincremental-instead, search-whitespace-regexp)
+ (search-invisible, isearch-hide-immediately)
+ (isearch-resume-in-command-history, search-ring-max)
+ (regexp-search-ring-max, search-ring-update, search-highlight)
+ (isearch-fail): Delete :group entries.
+
+2015-10-24 Artur Malabarba <bruce.connor.am@gmail.com>
+
+ * lisp/custom.el (custom-declare-variable): Shorten code a bit.
+
+2015-10-24 Juanma Barranquero <lekktu@gmail.com>
+
+ addpm.c: Silence some warnings.
+
+ * nt/addpm.c (DdeCommand): Cast pData argument of DdeClientTransaction
+ to LPBYTE.
+ (add_registry): Pass NULL to optional lpClass argument of
+ RegCreateKeyEx, not an empty string.
+
+2015-10-24 Juanma Barranquero <lekktu@gmail.com>
+
+ addpm.c: Do not add obsolete GTK libraries to the path.
+
+ * nt/addpm.c (REG_GTK, REG_RUNEMACS_PATH): Delete.
+ (add_registry): Remove variables `size' and `gtk_key'.
+ Do not add the GTK DLL directory to the library search path; it is
+ confusing behavior (in particular, the same Emacs version with and
+ without invoking addpm will use a different path), and the GTK image
+ libraries are obsolete anyway.
+
+2015-10-24 Juanma Barranquero <lekktu@gmail.com>
+
+ addpm.c: Replace existing registry entries, but do not create new ones
+
+ * nt/addpm.c (add_registry): If the Emacs registry key exists, replace
+ existing values from previous versions, but do not add new ones; the
+ key could exist for other reasons unrelated to old Emacsen, like X-style
+ resources, or to set some environment variables like HOME or LANG, and
+ in that case we don't want to populate it with obsolete values.
+
+2015-10-24 Juanma Barranquero <lekktu@gmail.com>
+
+ * nt/addpm.c (add_registry): Do not compute unused return value.
+
+2015-10-24 Juanma Barranquero <lekktu@gmail.com>
+
+ addpm.c: Don't pass REG_OPTION_NON_VOLATILE to RegOpenKeyEx
+
+ * nt/addpm.c (add_registry): Pass 0 to ulOptions argument of
+ RegOpenKeyEx, not REG_OPTION_NON_VOLATILE. This doesn't change
+ current behavior because REG_OPTION_NON_VOLATILE is defined to
+ be 0L anyway, but that option is actually documented only for
+ RegCreateKeyEx.
+
+2015-10-24 Juanma Barranquero <lekktu@gmail.com>
+
+ * src/w32notify.c (Fw32notify_add_watch): Fix version check.
+
+2015-10-24 Eli Zaretskii <eliz@gnu.org>
+
+ Update frame title when redisplay scrolls selected window
+
+ * src/xdisp.c (redisplay_window): Reconsider the frame's title
+ when the mode-line of the frame's selected window needs to be
+ updated.
+
+2015-10-24 Eli Zaretskii <eliz@gnu.org>
+
+ Update frame title when scrolling the selected window
+
+ * src/window.c (wset_update_mode_line): New function, sets either
+ the window's update_mode_line flag or the global update_mode_lines
+ variable.
+ (Fset_window_start, set_window_buffer, window_scroll_pixel_based)
+ (window_scroll_line_based): Call it instead of only setting the
+ window's update_mode_line flag.
+
+2015-10-24 Eli Zaretskii <eliz@gnu.org>
+
+ An even better fix for bug#21739
+
+ * src/window.c (set_window_buffer): If the window is the frame's
+ selected window, set update_mode_lines, not the window's
+ update_mode_line flag.
+ * src/buffer.c (Fkill_buffer): Undo last change.
+ (set_update_modelines_for_buf): Function deleted.
+
+2015-10-24 Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ Alexandru Harsanyi <AlexHarsanyi@gmail.com>
+
+ Sync with soap-client repository, version 3.0.0
+
* lisp/net/soap-client.el, lisp/net/soap-inspect.el:
Bump version to 3.0.0.
* lisp/net/soap-client.el (soap-invoke): Encode the string for
`url-request-data' as UTF-8. Fixes issue 16.
-2015-10-25 Eli Zaretskii <eliz@gnu.org>
-
- * lisp/progmodes/grep.el (grep): Doc fix. (Bug#21754)
-
-2015-10-25 Artur Malabarba <bruce.connor.am@gmail.com>
-
- * src/keyboard.c (post-command-hook): Extend the docstring.
- Mainly, explain how to use it without hanging Emacs, or giving the
- impression that it is hanging. Also mention `pre-command-hook'.
- (pre-command-hook): Mention `post-command-hook'.
-
-2015-10-25 Artur Malabarba <bruce.connor.am@gmail.com>
-
- * lisp/custom.el (custom-declare-variable): Shorten code again.
- Without using pcase this time. We can't use pcase because it is
- loaded after custom in loadup.el. Also add a comment explaining
- this to future dummies like me.
-
-2015-10-25 Michael Albinus <michael.albinus@gmx.de>
-
- * doc/lispref/os.texi (File Notifications): Document `stopped event'.
-
-2015-10-25 Michael Albinus <michael.albinus@gmx.de>
-
- Introduce `stopped' event in file notification
-
- * lisp/filenotify.el (file-notify--rm-descriptor): New defun.
- (file-notify-rm-watch): Use it.
- (file-notify-callback): Implement `stopped' event.
- (file-notify-add-watch): Mention `stopped' in the docstring.
- Check, that upper directory exists.
-
- * test/automated/file-notify-tests.el (file-notify-test01-add-watch):
- Add two test cases.
- (file-notify-test02-events): Handle also `stopped' event.
- (file-notify-test04-file-validity): Add another test case.
-
-2015-10-25 Paul Eggert <eggert@cs.ucla.edu>
-
- Revert commit that broke 'make bootstrap'
-
- * lisp/custom.el (custom-declare-variable): Revert commit
- 79fac080d277fed07b3c192890ad59d36d9f83b6. custom.el needs to work
- even when pcase has not been defined yet, when doing bootstrapping.
-
-2015-10-25 Paul Eggert <eggert@cs.ucla.edu>
-
- Port recent inline functions fix to Standard C
-
- * src/lisp.h (LISP_MACRO_DEFUN, LISP_MACRO_DEFUN_VOID): Remove.
- All uses rewritten to define the function directly rather than to
- use a macro to define the function. This conforms to Standard C,
- which does not allow stray semicolons at the top level. I hope it
- also avoids the problems with TAGS. Those macros, though clever,
- were pretty confusing anyway, and it wasn’t clear they were worth
- the aggravation even without the TAGS problem.
-
-2015-10-24 Artur Malabarba <bruce.connor.am@gmail.com>
-
- * lisp/isearch.el: Make character-fold search the default again.
-
-2015-10-24 Artur Malabarba <bruce.connor.am@gmail.com>
-
- * lisp/character-fold.el: Many improvements.
- (character-fold-search-forward, character-fold-search-backward):
- New command.
- (character-fold-to-regexp): Remove lax-whitespace hack.
- (character-fold-search): Remove variable. Only isearch and
- query-replace use char-folding, and they both have their own
- variables to configure that.
-
-2015-10-24 Artur Malabarba <bruce.connor.am@gmail.com>
-
- * lisp/isearch.el: Generalize definition of regexp-function toggles.
- (isearch-specify-regexp-function): New macro for specifying
- possible values of `isearch-regexp-function'.
- (isearch-toggle-character-fold, isearch-toggle-symbol)
- (isearch-toggle-word): Define with `isearch-specify-regexp-function'.
-
-2015-10-24 Artur Malabarba <bruce.connor.am@gmail.com>
-
- * lisp/isearch.el (search-default-regexp-mode): New variable.
- (isearch-mode): Use it.
-
-2015-10-24 Artur Malabarba <bruce.connor.am@gmail.com>
-
- * lisp/isearch.el (search-exit-option, search-slow-window-lines)
- (search-slow-speed, search-upper-case)
- (search-nonincremental-instead, search-whitespace-regexp)
- (search-invisible, isearch-hide-immediately)
- (isearch-resume-in-command-history, search-ring-max)
- (regexp-search-ring-max, search-ring-update, search-highlight)
- (isearch-fail): Delete :group entries.
-
-2015-10-24 Artur Malabarba <bruce.connor.am@gmail.com>
-
- * lisp/custom.el (custom-declare-variable): Shorten code a bit.
-
-2015-10-24 Juanma Barranquero <lekktu@gmail.com>
-
- addpm.c: Silence some warnings.
-
- * nt/addpm.c (DdeCommand): Cast pData argument of DdeClientTransaction
- to LPBYTE.
- (add_registry): Pass NULL to optional lpClass argument of
- RegCreateKeyEx, not an empty string.
-
-2015-10-24 Juanma Barranquero <lekktu@gmail.com>
-
- addpm.c: Do not add obsolete GTK libraries to the path.
-
- * nt/addpm.c (REG_GTK, REG_RUNEMACS_PATH): Delete.
- (add_registry): Remove variables `size' and `gtk_key'.
- Do not add the GTK DLL directory to the library search path; it is
- confusing behavior (in particular, the same Emacs version with and
- without invoking addpm will use a different path), and the GTK image
- libraries are obsolete anyway.
-
-2015-10-24 Juanma Barranquero <lekktu@gmail.com>
-
- addpm.c: Replace existing registry entries, but do not create new ones
-
- * nt/addpm.c (add_registry): If the Emacs registry key exists, replace
- existing values from previous versions, but do not add new ones; the
- key could exist for other reasons unrelated to old Emacsen, like X-style
- resources, or to set some environment variables like HOME or LANG, and
- in that case we don't want to populate it with obsolete values.
-
-2015-10-24 Juanma Barranquero <lekktu@gmail.com>
-
- * nt/addpm.c (add_registry): Do not compute unused return value.
-
-2015-10-24 Juanma Barranquero <lekktu@gmail.com>
-
- addpm.c: Don't pass REG_OPTION_NON_VOLATILE to RegOpenKeyEx
-
- * nt/addpm.c (add_registry): Pass 0 to ulOptions argument of
- RegOpenKeyEx, not REG_OPTION_NON_VOLATILE. This doesn't change
- current behavior because REG_OPTION_NON_VOLATILE is defined to
- be 0L anyway, but that option is actually documented only for
- RegCreateKeyEx.
-
-2015-10-24 Juanma Barranquero <lekktu@gmail.com>
-
- * src/w32notify.c (Fw32notify_add_watch): Fix version check.
-
-2015-10-24 Eli Zaretskii <eliz@gnu.org>
-
- Update frame title when redisplay scrolls selected window
-
- * src/xdisp.c (redisplay_window): Reconsider the frame's title
- when the mode-line of the frame's selected window needs to be
- updated.
-
-2015-10-24 Eli Zaretskii <eliz@gnu.org>
-
- Update frame title when scrolling the selected window
-
- * src/window.c (wset_update_mode_line): New function, sets either
- the window's update_mode_line flag or the global update_mode_lines
- variable.
- (Fset_window_start, set_window_buffer, window_scroll_pixel_based)
- (window_scroll_line_based): Call it instead of only setting the
- window's update_mode_line flag.
-
-2015-10-24 Eli Zaretskii <eliz@gnu.org>
-
- An even better fix for bug#21739
-
- * src/window.c (set_window_buffer): If the window is the frame's
- selected window, set update_mode_lines, not the window's
- update_mode_line flag.
- * src/buffer.c (Fkill_buffer): Undo last change.
- (set_update_modelines_for_buf): Function deleted.
-
-2015-10-24 Thomas Fitzsimmons <fitzsim@fitzsim.org>
-
- Sync with soap-client repository, version 3.0.0
-
2015-10-24 Nicolas Petton <nicolas@petton.fr>
Update the new icon
This file records repository revisions from
commit 9d56a21e6a696ad19ac65c4b405aeca44785884a (exclusive) to
-commit cb56d4cec80a4da41710e2fa68dcd3d95e2a8e4c (inclusive).
+commit 8a8613bcf4227dfe46a694b761e9575bdf6ca2ce (inclusive).
See ChangeLog.1 for earlier changes.
;; Local Variables:
feature. Unless you really need some change that was done on the
master while you were developing on the branch, you don't really need
those merges; just merge once, when you are done with the feature, and
-Bazaar will take care of the rest. Bazaar is much better in this than
-CVS, so interim merges are unnecessary.
+Git will take care of the rest. Git is much better in this than CVS,
+so interim merges are unnecessary.
Or use shelves; or rebase; or do something else. See the thread for
yet another fun excursion into the exciting world of version control.
@group
(let ((edges (window-absolute-body-pixel-edges))
(position (pos-visible-in-window-p nil nil t)))
- (x-set-mouse-absolute-pixel-position
+ (set-mouse-absolute-pixel-position
(+ (nth 0 edges) (nth 0 position))
(+ (nth 1 edges) (nth 1 position))))
@end group
\f
* Changes in Specialized Modes and Packages in Emacs 25.1
+** New function `bookmark-set-no-overwrite' bound to C-x r M.
+It raises an error if a bookmark of that name already exists,
+unlike `bookmark-set' which silently updates an existing bookmark.
+
** JSON
---
*** `json-pretty-print' and `json-pretty-print-buffer' now maintain
The INT_<op>_OVERFLOW macros return 1 if the corresponding C operators
might not yield numerically correct answers due to arithmetic overflow.
- The INT_<op>_WRAPV macros return the low-order bits of the answer.
- For example, INT_ADD_WRAPV (INT_MAX, 1) returns INT_MIN on a two's
- complement host, even if INT_MAX + 1 would trap.
-
+ The INT_<op>_WRAPV macros also store the low-order bits of the answer.
These macros work correctly on all known practical hosts, and do not rely
on undefined behavior due to signed arithmetic overflow.
- Example usage:
+ Example usage, assuming A and B are long int:
- long int a = ...;
- long int b = ...;
long int result = INT_MULTIPLY_WRAPV (a, b);
printf ("result is %ld (%s)\n", result,
INT_MULTIPLY_OVERFLOW (a, b) ? "after overflow" : "no overflow");
- enum {
- INT_PRODUCTS_FIT_IN_LONG
- = ! INT_CONST_MULTIPLY_OVERFLOW ((long int) INT_MIN, INT_MIN)
- };
+ Example usage with WRAPV flavor:
+
+ long int result;
+ bool overflow = INT_MULTIPLY_WRAPV (a, b, &result);
+ printf ("result is %ld (%s)\n", result,
+ overflow ? "after overflow" : "no overflow");
Restrictions on these macros:
These macros may evaluate their arguments zero or multiple times, so the
arguments should not have side effects.
- On non-GCC-compatible compilers that do not support C11, the type
- of INT_<op>_WRAPV (A, B) might differ from the native type of (A op
- B), so it is wise to convert the result to the native type. Such a
- conversion is safe and cannot trap.
-
- For runtime efficiency GCC 5 and later has builtin functions for +,
- -, * when doing integer overflow checking or wraparound arithmetic.
- Unfortunately, these builtins require nonnull pointer arguments and
- so cannot be used in constant expressions; see GCC bug 68120
- <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68120>. In constant
- expressions, use the macros INT_CONST_ADD_OVERFLOW and
- INT_CONST_ADD_WRAPV instead, and similarly for SUBTRACT and
- MULTIPLY; these macros avoid the builtins and are slower in
- non-constant expressions. Perhaps someday GCC's API for overflow
- checking will be improved and we can remove the need for the
- INT_CONST_ variants.
+ The WRAPV macros are not constant expressions. They support only
+ +, binary -, and *. The result type must be signed.
These macros are tuned for their last argument being a constant.
Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B,
A % B, and A << B would overflow, respectively. */
-#define INT_CONST_ADD_OVERFLOW(a, b) \
+#define INT_ADD_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW)
-#define INT_CONST_SUBTRACT_OVERFLOW(a, b) \
+#define INT_SUBTRACT_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW)
#define INT_NEGATE_OVERFLOW(a) \
INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
-#define INT_CONST_MULTIPLY_OVERFLOW(a, b) \
+#define INT_MULTIPLY_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)
#define INT_DIVIDE_OVERFLOW(a, b) \
_GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW)
_GL_INT_MINIMUM (0 * (b) + (a)), \
_GL_INT_MAXIMUM (0 * (b) + (a)))
-/* Return the low order bits of the integer expressions
- A * B, A - B, -A, A * B, A / B, A % B, and A << B, respectively.
- See above for restrictions. */
-#define INT_CONST_ADD_WRAPV(a, b) _GL_INT_OP_WRAPV (a, b, +)
-#define INT_CONST_SUBTRACT_WRAPV(a, b) _GL_INT_OP_WRAPV (a, b, -)
-#define INT_NEGATE_WRAPV(a) INT_CONST_SUBTRACT_WRAPV (0, a)
-#define INT_CONST_MULTIPLY_WRAPV(a, b) _GL_INT_OP_WRAPV (a, b, *)
-#define INT_DIVIDE_WRAPV(a, b) \
- (INT_DIVIDE_OVERFLOW(a, b) ? INT_NEGATE_WRAPV (a) : (a) / (b))
-#define INT_REMAINDER_WRAPV(a, b) \
- (INT_REMAINDER_OVERFLOW(a, b) ? 0 : (a) % (b))
-#define INT_LEFT_SHIFT_WRAPV(a, b) _GL_INT_OP_WRAPV (a, b, <<)
-
-/* Return the low order bits of A <op> B, where OP specifies the operation.
- See above for restrictions. */
-#if !_GL_HAVE___TYPEOF__ && 201112 <= __STDC_VERSION__
-# define _GL_INT_OP_WRAPV(a, b, op) \
- _Generic ((a) op (b), \
- int: _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, int), \
- long int: _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long int), \
- long long int: _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, \
- long long int), \
- default: (a) op (b))
+/* Compute A + B, A - B, A * B, respectively, storing the result into *R.
+ Return 1 if the result overflows. See above for restrictions. */
+#define INT_ADD_WRAPV(a, b, r) \
+ _GL_INT_OP_WRAPV (a, b, r, +, __builtin_add_overflow, INT_ADD_OVERFLOW)
+#define INT_SUBTRACT_WRAPV(a, b, r) \
+ _GL_INT_OP_WRAPV (a, b, r, -, __builtin_sub_overflow, INT_SUBTRACT_OVERFLOW)
+#define INT_MULTIPLY_WRAPV(a, b, r) \
+ _GL_INT_OP_WRAPV (a, b, r, *, __builtin_mul_overflow, INT_MULTIPLY_OVERFLOW)
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390. See:
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193
+ https://llvm.org/bugs/show_bug.cgi?id=25390
+ For now, assume all versions of GCC-like compilers generate bogus
+ warnings for _Generic. This matters only for older compilers that
+ lack __builtin_add_overflow. */
+#if __GNUC__
+# define _GL__GENERIC_BOGUS 1
#else
-# define _GL_INT_OP_WRAPV(a, b, op) \
- (! _GL_INT_SIGNED ((0 * (a)) op (0 * (b))) \
- ? ((a) op (b)) \
- : _GL_EXPR_CAST ((a) op (b), \
- (sizeof ((a) op (b)) <= sizeof (int) \
- ? _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, int) \
- : _GL_INT_OP_WRAPV_LONGISH (a, b, op))))
-
-/* Cast to E's type the value of V if possible. Yield V as-is otherwise. */
-# if _GL_HAVE___TYPEOF__
-# define _GL_EXPR_CAST(e, v) ((__typeof__ (e)) (v))
-# else
-# define _GL_EXPR_CAST(e, v) (v)
-# endif
+# define _GL__GENERIC_BOGUS 0
+#endif
+/* Store A <op> B into *R, where OP specifies the operation.
+ BUILTIN is the builtin operation, and OVERFLOW the overflow predicate.
+ See above for restrictions. */
+#if 5 <= __GNUC__ || __has_builtin (__builtin_add_oveflow)
+# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) builtin (a, b, r)
+#elif 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS
+# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
+ (_Generic \
+ (*(r), \
+ signed char: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned char, \
+ signed char, SCHAR_MIN, SCHAR_MAX), \
+ short int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned short int, \
+ short int, SHRT_MIN, SHRT_MAX), \
+ int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ int, INT_MIN, INT_MAX), \
+ long int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ long int, LONG_MIN, LONG_MAX), \
+ long long int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+ long long int, LLONG_MIN, LLONG_MAX)))
+#else
+# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
+ (sizeof *(r) == sizeof (signed char) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned char, \
+ signed char, SCHAR_MIN, SCHAR_MAX) \
+ : sizeof *(r) == sizeof (short int) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned short int, \
+ short int, SHRT_MIN, SHRT_MAX) \
+ : sizeof *(r) == sizeof (int) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ int, INT_MIN, INT_MAX) \
+ : _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow))
# ifdef LLONG_MAX
-# define _GL_INT_OP_WRAPV_LONGISH(a, b, op) \
- (sizeof ((a) op (b)) <= sizeof (long int) \
- ? _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long int) \
- : _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long long int))
+# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
+ (sizeof *(r) == sizeof (long int) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ long int, LONG_MIN, LONG_MAX) \
+ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+ long long int, LLONG_MIN, LLONG_MAX))
# else
-# define _GL_INT_OP_WRAPV_LONGISH(a, b, op) \
- _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, long int)
+# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ long int, LONG_MIN, LONG_MAX))
# endif
#endif
-/* Return A <op> B, where the operation is given by OP and the result
- type is T. T is a signed integer type that is at least as wide as int.
- Do arithmetic using 'unsigned T' to avoid signed integer overflow.
- Subtract TYPE_MINIMUM (T) before converting back to T, and add it
- back afterwards, to avoid signed overflow during conversion. */
-#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, t) \
- ((unsigned t) (a) op (unsigned t) (b) <= TYPE_MAXIMUM (t) \
- ? (t) ((unsigned t) (a) op (unsigned t) (b)) \
- : ((t) ((unsigned t) (a) op (unsigned t) (b) - TYPE_MINIMUM (t)) \
- + TYPE_MINIMUM (t)))
-
-/* Calls to the INT_<op>_<result> macros are like their INT_CONST_<op>_<result>
- counterparts, except they are faster with GCC 5 or later, and they
- are not constant expressions due to limitations in the GNU C API. */
-
-#define INT_ADD_OVERFLOW(a, b) \
- _GL_OP_OVERFLOW (a, b, INT_CONST_ADD_OVERFLOW, __builtin_add_overflow)
-#define INT_SUBTRACT_OVERFLOW(a, b) \
- _GL_OP_OVERFLOW (a, b, INT_CONST_SUBTRACT_OVERFLOW, __builtin_sub_overflow)
-#define INT_MULTIPLY_OVERFLOW(a, b) \
- _GL_OP_OVERFLOW (a, b, INT_CONST_MULTIPLY_OVERFLOW, __builtin_mul_overflow)
-
-#define INT_ADD_WRAPV(a, b) \
- _GL_OP_WRAPV (a, b, INT_CONST_ADD_WRAPV, __builtin_add_overflow)
-#define INT_SUBTRACT_WRAPV(a, b) \
- _GL_OP_WRAPV (a, b, INT_CONST_SUBTRACT_WRAPV, __builtin_sub_overflow)
-#define INT_MULTIPLY_WRAPV(a, b) \
- _GL_OP_WRAPV (a, b, INT_CONST_MULTIPLY_WRAPV, __builtin_mul_overflow)
-
-#if __GNUC__ < 5
-# define _GL_OP_OVERFLOW(a, b, portable, builtin) portable (a, b)
-# define _GL_OP_WRAPV(a, b, portable, builtin) portable (a, b)
-#else
-# define _GL_OP_OVERFLOW(a, b, portable, builtin) \
- builtin (a, b, &(__typeof__ ((a) + (b))) {0})
-# define _GL_OP_WRAPV(a, b, portable, builtin) \
- _GL_OP_WRAPV_GENSYM(a, b, builtin, __gl_wrapv##__COUNTER__)
-# define _GL_OP_WRAPV_GENSYM(a, b, builtin, r) \
- ({__typeof__ ((a) + (b)) r; builtin (a, b, &r); r; })
-#endif
+/* Store the low-order bits of A <op> B into *R, where the operation
+ is given by OP. Use the unsigned type UT for calculation to avoid
+ overflow problems. *R's type is T, with extremal values TMIN and
+ TMAX. T must be a signed integer type. */
+#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \
+ (sizeof ((a) op (b)) < sizeof (t) \
+ ? _GL_INT_OP_CALC1 ((t) (a), (t) (b), r, op, overflow, ut, t, tmin, tmax) \
+ : _GL_INT_OP_CALC1 (a, b, r, op, overflow, ut, t, tmin, tmax))
+#define _GL_INT_OP_CALC1(a, b, r, op, overflow, ut, t, tmin, tmax) \
+ ((overflow (a, b) \
+ || (_GL_INT_SIGNED ((a) op (b)) && ((a) op (b)) < (tmin)) \
+ || (tmax) < ((a) op (b))) \
+ ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t, tmin, tmax), 1) \
+ : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t, tmin, tmax), 0))
+
+/* Return A <op> B, where the operation is given by OP. Use the
+ unsigned type UT for calculation to avoid overflow problems.
+ Convert the result to type T without overflow by subtracting TMIN
+ from large values before converting, and adding it afterwards.
+ Compilers can optimize all the operations except OP. */
+#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t, tmin, tmax) \
+ (((ut) (a) op (ut) (b)) <= (tmax) \
+ ? (t) ((ut) (a) op (ut) (b)) \
+ : ((t) (((ut) (a) op (ut) (b)) - (tmin)) + (tmin)))
#endif /* _GL_INTPROPS_H */
int ns = a.tv_nsec + b.tv_nsec;
int nsd = ns - TIMESPEC_RESOLUTION;
int rns = ns;
+ time_t tmin = TYPE_MINIMUM (time_t);
+ time_t tmax = TYPE_MAXIMUM (time_t);
if (0 <= nsd)
{
rns = nsd;
- if (rs == TYPE_MAXIMUM (time_t))
- {
- if (0 <= bs)
- goto high_overflow;
- bs++;
- }
- else
+ if (bs < tmax)
+ bs++;
+ else if (rs < 0)
rs++;
+ else
+ goto high_overflow;
}
- if (INT_ADD_OVERFLOW (rs, bs))
+ /* INT_ADD_WRAPV is not appropriate since time_t might be unsigned.
+ In theory time_t might be narrower than int, so plain
+ INT_ADD_OVERFLOW does not suffice. */
+ if (! INT_ADD_OVERFLOW (rs, bs) && tmin <= rs + bs && rs + bs <= tmax)
+ rs += bs;
+ else
{
if (rs < 0)
{
- rs = TYPE_MINIMUM (time_t);
+ rs = tmin;
rns = 0;
}
else
{
high_overflow:
- rs = TYPE_MAXIMUM (time_t);
+ rs = tmax;
rns = TIMESPEC_RESOLUTION - 1;
}
}
- else
- rs += bs;
return make_timespec (rs, rns);
}
time_t bs = b.tv_sec;
int ns = a.tv_nsec - b.tv_nsec;
int rns = ns;
+ time_t tmin = TYPE_MINIMUM (time_t);
+ time_t tmax = TYPE_MAXIMUM (time_t);
if (ns < 0)
{
rns = ns + TIMESPEC_RESOLUTION;
- if (rs == TYPE_MINIMUM (time_t))
- {
- if (bs <= 0)
- goto low_overflow;
- bs--;
- }
- else
+ if (bs < tmax)
+ bs++;
+ else if (- TYPE_SIGNED (time_t) < rs)
rs--;
+ else
+ goto low_overflow;
}
- if (INT_SUBTRACT_OVERFLOW (rs, bs))
+ /* INT_SUBTRACT_WRAPV is not appropriate since time_t might be unsigned.
+ In theory time_t might be narrower than int, so plain
+ INT_SUBTRACT_OVERFLOW does not suffice. */
+ if (! INT_SUBTRACT_OVERFLOW (rs, bs) && tmin <= rs - bs && rs - bs <= tmax)
+ rs -= bs;
+ else
{
if (rs < 0)
{
low_overflow:
- rs = TYPE_MINIMUM (time_t);
+ rs = tmin;
rns = 0;
}
else
{
- rs = TYPE_MAXIMUM (time_t);
+ rs = tmax;
rns = TIMESPEC_RESOLUTION - 1;
}
}
- else
- rs -= bs;
return make_timespec (rs, rns);
}
,@(if (cadr props) (list :system (cadr props))))))
(unless (plist-get props :count)
(setq props (plist-put props :count 0)))
+ (setq props (plist-put props :abbrev-table-modiff
+ (abbrev-table-get table :abbrev-table-modiff)))
(let ((system-flag (plist-get props :system))
(sym (intern name table)))
;; Don't override a prior user-defined abbrev with a system abbrev,
;;;###autoload (define-key ctl-x-r-map "b" 'bookmark-jump)
;;;###autoload (define-key ctl-x-r-map "m" 'bookmark-set)
+;;;###autoload (define-key ctl-x-r-map "M" 'bookmark-set-no-overwrite)
;;;###autoload (define-key ctl-x-r-map "l" 'bookmark-bmenu-list)
;;;###autoload
;; Read the help on all of these functions for details...
(define-key map "x" 'bookmark-set)
(define-key map "m" 'bookmark-set) ;"m"ark
+ (define-key map "M" 'bookmark-set-no-overwrite) ;"M"aybe mark
(define-key map "j" 'bookmark-jump)
(define-key map "g" 'bookmark-jump) ;"g"o
(define-key map "o" 'bookmark-jump-other-window)
map))
;;;###autoload
-(defun bookmark-set (&optional name no-overwrite)
- "Set a bookmark named NAME at the current location.
-If name is nil, then prompt the user.
-
-With a prefix arg (non-nil NO-OVERWRITE), do not overwrite any
-existing bookmark that has the same name as NAME, but instead push the
-new bookmark onto the bookmark alist. The most recently set bookmark
-with name NAME is thus the one in effect at any given time, but the
-others are still there, should the user decide to delete the most
-recent one.
-
-To yank words from the text of the buffer and use them as part of the
-bookmark name, type C-w while setting a bookmark. Successive C-w's
-yank successive words.
-
-Typing C-u inserts (at the bookmark name prompt) the name of the last
-bookmark used in the document where the new bookmark is being set;
-this helps you use a single bookmark name to track progress through a
-large document. If there is no prior bookmark for this document, then
-C-u inserts an appropriate name based on the buffer or file.
-
-Use \\[bookmark-delete] to remove bookmarks (you give it a name and
-it removes only the first instance of a bookmark with that name from
-the list of bookmarks.)"
+(defun bookmark-set-internal (prompt name overwrite-or-push)
+ "Interactively set a bookmark named NAME at the current location.
+
+Begin the interactive prompt with PROMPT, followed by a space, a
+generated default name in parentheses, a colon and a space.
+
+If OVERWRITE-OR-PUSH is nil, then error if there is already a
+bookmark named NAME; if `overwrite', then replace any existing
+bookmark if there is one; if `push' then push the new bookmark
+onto the bookmark alist. The `push' behavior means that among
+bookmarks named NAME, this most recently set one becomes the one in
+effect, but the others are still there, in order, if the topmost one
+is ever deleted."
(interactive (list nil current-prefix-arg))
(unwind-protect
(let* ((record (bookmark-make-record))
(let ((str
(or name
(read-from-minibuffer
- (format "Set bookmark (%s): " default)
+ (format "%s (default: \"%s\"): " prompt default)
nil
bookmark-minibuffer-read-name-map
nil nil defaults))))
(and (string-equal str "") (setq str default))
- (bookmark-store str (cdr record) no-overwrite)
+
+ (cond
+ ((eq overwrite-or-push nil)
+ (if (bookmark-get-bookmark str t)
+ (error "A bookmark named \"%s\" already exists." str)
+ (bookmark-store str (cdr record) nil)))
+ ((eq overwrite-or-push 'overwrite)
+ (bookmark-store str (cdr record) nil))
+ ((eq overwrite-or-push 'push)
+ (bookmark-store str (cdr record) t))
+ (t
+ (error "Unrecognized value for `overwrite-or-push': %S"
+ overwrite-or-push)))
;; Ask for an annotation buffer for this bookmark
(when bookmark-use-annotations
(setq bookmark-current-buffer nil)))
+(defun bookmark-set (&optional name no-overwrite)
+ "Set a bookmark named NAME at the current location.
+If NAME is nil, then prompt the user.
+
+With a prefix arg (non-nil NO-OVERWRITE), do not overwrite any
+existing bookmark that has the same name as NAME, but instead push the
+new bookmark onto the bookmark alist. The most recently set bookmark
+with name NAME is thus the one in effect at any given time, but the
+others are still there, should the user decide to delete the most
+recent one.
+
+To yank words from the text of the buffer and use them as part of the
+bookmark name, type C-w while setting a bookmark. Successive C-w's
+yank successive words.
+
+Typing C-u inserts (at the bookmark name prompt) the name of the last
+bookmark used in the document where the new bookmark is being set;
+this helps you use a single bookmark name to track progress through a
+large document. If there is no prior bookmark for this document, then
+C-u inserts an appropriate name based on the buffer or file.
+
+Use \\[bookmark-delete] to remove bookmarks (you give it a name and
+it removes only the first instance of a bookmark with that name from
+the list of bookmarks.)"
+ (interactive (list nil current-prefix-arg))
+ (let ((prompt
+ (if no-overwrite "Set bookmark" "Set bookmark unconditionally")))
+ (bookmark-set-internal prompt name (if no-overwrite 'push 'overwrite))))
+
+(defun bookmark-set-no-overwrite (&optional name push-bookmark)
+ "Set a bookmark named NAME at the current location.
+If NAME is nil, then prompt the user.
+
+If a bookmark named NAME already exists and prefix argument
+PUSH-BOOKMARK is non-nil, then push the new bookmark onto the
+bookmark alist. Pushing it means that among bookmarks named
+NAME, this one becomes the one in effect, but the others are
+still there, in order, and become effective again if the user
+ever deletes the most recent one.
+
+Otherwise, if a bookmark named NAME already exists but PUSH-BOOKMARK
+is nil, raise an error.
+
+To yank words from the text of the buffer and use them as part of the
+bookmark name, type C-w while setting a bookmark. Successive C-w's
+yank successive words.
+
+Typing C-u inserts (at the bookmark name prompt) the name of the last
+bookmark used in the document where the new bookmark is being set;
+this helps you use a single bookmark name to track progress through a
+large document. If there is no prior bookmark for this document, then
+C-u inserts an appropriate name based on the buffer or file.
+
+Use \\[bookmark-delete] to remove bookmarks (you give it a name and
+it removes only the first instance of a bookmark with that name from
+the list of bookmarks.)"
+ (interactive (list nil current-prefix-arg))
+ (bookmark-set-internal "Set bookmark" name (if push-bookmark 'push nil)))
+
+
(defun bookmark-kill-line (&optional newline-too)
"Kill from point to end of line.
If optional arg NEWLINE-TOO is non-nil, delete the newline too.
slots defaults)))
(push `(cl-defsubst ,cname
(&cl-defs (nil ,@descs) ,@args)
- ,(if (stringp doc) (list doc)
+ ,(if (stringp doc) doc
(format "Constructor for objects of type `%s'." name))
,@(if (cl--safe-expr-p `(progn ,@(mapcar #'cl-second descs)))
'((declare (side-effect-free t))))
+2015-11-07 Kelvin White <kwhite@gnu.org>
+
+ * erc-pcomplete.el (pcomplete-erc-nicks): Fix bug for tab complete
+ (bug#18771)
+
2015-03-25 Stefan Monnier <monnier@iro.umontreal.ca>
* erc.el (erc-switch-to-buffer): Fix last change (bug#20187).
(erc-get-channel-user-list)))
(nicks nil))
(dolist (user users)
- (unless (and ignore-self
- (string= (erc-server-user-nickname (car user))
- (erc-current-nick)))
+ (unless (or (not user)
+ (and ignore-self
+ (string= (erc-server-user-nickname (car user))
+ (erc-current-nick))))
(setq nicks (cons (concat (erc-server-user-nickname (car user))
postfix)
nicks))))
;; Send `stopped' event.
(dolist (entry (cdr registered))
(funcall (cdr entry)
- `(,(file-notify--descriptor desc) stopped
+ `(,descriptor stopped
,(or (and (stringp (car entry))
(expand-file-name (car entry) dir))
dir))))
;; `inotify' returns the same descriptor when the file (directory)
;; uses the same inode. We want to distinguish, and apply a virtual
;; descriptor which make the difference.
-(defun file-notify--descriptor (descriptor)
+(defun file-notify--descriptor (desc file)
"Return the descriptor to be used in `file-notify-*-watch'.
For `gfilenotify' and `w32notify' it is the same descriptor as
used in the low-level file notification package."
- (if (and (natnump descriptor) (eq file-notify--library 'inotify))
- (cons descriptor
- (car (cadr (gethash descriptor file-notify-descriptors))))
- descriptor))
+ (if (and (natnump desc) (eq file-notify--library 'inotify))
+ (cons desc
+ (and (stringp file)
+ (car (assoc
+ (file-name-nondirectory file)
+ (gethash desc file-notify-descriptors)))))
+ desc))
;; The callback function used to map between specific flags of the
;; respective file notifications, and the ones we return.
(car file-notify--pending-event)))
;; If the source is handled by another watch, we
;; must fire the rename event there as well.
- (when (not (equal (file-notify--descriptor desc)
+ (when (not (equal (file-notify--descriptor desc file1)
(file-notify--descriptor
- (caar file-notify--pending-event))))
+ (caar file-notify--pending-event)
+ (file-notify--event-file-name
+ file-notify--pending-event))))
(setq pending-event
`((,(caar file-notify--pending-event)
renamed ,file ,file1)
;; Apply pending callback.
(when pending-event
(setcar
- (car pending-event) (file-notify--descriptor (caar pending-event)))
+ (car pending-event)
+ (file-notify--descriptor
+ (caar pending-event)
+ (file-notify--event-file-name file-notify--pending-event)))
(funcall (cadr pending-event) (car pending-event))
(setq pending-event nil))
(if file1
(funcall
callback
- `(,(file-notify--descriptor desc) ,action ,file ,file1))
+ `(,(file-notify--descriptor desc file) ,action ,file ,file1))
(funcall
callback
- `(,(file-notify--descriptor desc) ,action ,file)))))
+ `(,(file-notify--descriptor desc file) ,action ,file)))))
;; Modify `file-notify-descriptors'.
(when stopped
- (file-notify--rm-descriptor (file-notify--descriptor desc) file)))))
+ (file-notify--rm-descriptor
+ (file-notify--descriptor desc file) file)))))
;; `gfilenotify' and `w32notify' return a unique descriptor for every
;; `file-notify-add-watch', while `inotify' returns a unique
file-notify-descriptors)
;; Return descriptor.
- (file-notify--descriptor desc)))
+ (file-notify--descriptor
+ desc (unless (file-directory-p file) (file-name-nondirectory file)))))
(defun file-notify-rm-watch (descriptor)
"Remove an existing watch specified by its DESCRIPTOR.
(if handler
;; A file name handler could exist even if there is no local
;; file notification support.
- (funcall handler 'file-notify-rm-watch desc)
+ (funcall handler 'file-notify-rm-watch descriptor)
(funcall
(cond
(make-obsolete-variable
'window-system-version "it does not give useful information." "24.3")
+;; Variables which should trigger redisplay of the current buffer.
+(setq redisplay--variables (make-hash-table :test 'eq :size 10))
+(mapc (lambda (var)
+ (puthash var 1 redisplay--variables))
+ '(line-spacing
+ overline-margin
+ line-prefix
+ wrap-prefix))
+
(provide 'frame)
;;; frame.el ends here
"\M-\C-e" gnus-summary-expire-articles-now
"\177" gnus-summary-delete-article
[delete] gnus-summary-delete-article
+ [backspace] gnus-summary-delete-article
"m" gnus-summary-move-article
"r" gnus-summary-respool-article
"w" gnus-summary-edit-article
A sample format:
- HEX ADDR: 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f ASCII-TEXT
+ HEX ADDR: 0011 2233 4455 6677 8899 aabb ccdd eeff ASCII-TEXT
-------- ---- ---- ---- ---- ---- ---- ---- ---- ----------------
00000000: 5468 6973 2069 7320 6865 786c 2d6d 6f64 This is hexl-mod
00000010: 652e 2020 4561 6368 206c 696e 6520 7265 e. Each line re
"If non-nil, ] and } closings will be formatted lisp-style,
without indentation.")
+(defvar json-pre-element-read-function nil
+ "Function called (if non-nil) by `json-read-array' and
+`json-read-object' right before reading a JSON array or object,
+respectively. The function is called with one argument, which is
+the current JSON key.")
+
+(defvar json-post-element-read-function nil
+ "Function called (if non-nil) by `json-read-array' and
+`json-read-object' right after reading a JSON array or object,
+respectively.")
+
\f
;;; Utilities
\f
+;;; Paths
+
+(defvar json--path '()
+ "Used internally by `json-path-to-position' to keep track of
+the path during recursive calls to `json-read'.")
+
+(defun json--record-path (key)
+ "Record the KEY to the current JSON path.
+Used internally by `json-path-to-position'."
+ (push (cons (point) key) json--path))
+
+(defun json--check-position (position)
+ "Check if the last parsed JSON structure passed POSITION.
+Used internally by `json-path-to-position'."
+ (let ((start (caar json--path)))
+ (when (< start position (+ (point) 1))
+ (throw :json-path (list :path (nreverse (mapcar #'cdr json--path))
+ :match-start start
+ :match-end (point)))))
+ (pop json--path))
+
+(defun json-path-to-position (position &optional string)
+ "Return the path to the JSON element at POSITION.
+
+When STRING is provided, return the path to the position in the
+string, else to the position in the current buffer.
+
+The return value is a property list with the following
+properties:
+
+:path -- A list of strings and numbers forming the path to
+ the JSON element at the given position. Strings
+ denote object names, while numbers denote array
+ indexes.
+
+:match-start -- Position where the matched JSON element begins.
+
+:match-end -- Position where the matched JSON element ends.
+
+This can for instance be useful to determine the path to a JSON
+element in a deeply nested structure."
+ (save-excursion
+ (unless string
+ (goto-char (point-min)))
+ (let* ((json--path '())
+ (json-pre-element-read-function #'json--record-path)
+ (json-post-element-read-function
+ (apply-partially #'json--check-position position))
+ (path (catch :json-path
+ (if string
+ (json-read-from-string string)
+ (json-read)))))
+ (when (plist-get path :path)
+ path))))
+
;;; Keywords
(defvar json-keywords '("true" "false" "null")
(if (char-equal (json-peek) ?:)
(json-advance)
(signal 'json-object-format (list ":" (json-peek))))
+ (json-skip-whitespace)
+ (when json-pre-element-read-function
+ (funcall json-pre-element-read-function key))
(setq value (json-read))
+ (when json-post-element-read-function
+ (funcall json-post-element-read-function))
(setq elements (json-add-to-object elements key value))
(json-skip-whitespace)
(unless (char-equal (json-peek) ?})
;; read values until "]"
(let (elements)
(while (not (char-equal (json-peek) ?\]))
+ (json-skip-whitespace)
+ (when json-pre-element-read-function
+ (funcall json-pre-element-read-function (length elements)))
(push (json-read) elements)
+ (when json-post-element-read-function
+ (funcall json-post-element-read-function))
(json-skip-whitespace)
(unless (char-equal (json-peek) ?\])
(if (char-equal (json-peek) ?,)
(eval (eval-sexp-add-defvars (elisp--preceding-sexp)) lexical-binding)
eval-last-sexp-arg-internal)))
-
(defun elisp--eval-last-sexp-print-value (value &optional eval-last-sexp-arg-internal)
(let ((unabbreviated (let ((print-length nil) (print-level nil))
(prin1-to-string value)))
;; elisp function to remerge from the .BASE/OTHER/THIS files.
(smerge-start-session)
(add-hook 'after-save-hook 'vc-bzr-resolve-when-done nil t)
- (message "There are unresolved conflicts in this file")))
+ (vc-message-unresolved-conflicts buffer-file-name)))
(defun vc-bzr-version-dirstate (dir)
"Try to return as a string the bzr revision ID of directory DIR.
(smerge-start-session)
(when vc-git-resolve-conflicts
(add-hook 'after-save-hook 'vc-git-resolve-when-done nil 'local))
- (message "There are unresolved conflicts in this file")))
+ (vc-message-unresolved-conflicts buffer-file-name)))
;;; HISTORY FUNCTIONS
(vc-file-setprop buffer-file-name 'vc-state 'conflict)
(smerge-start-session)
(add-hook 'after-save-hook 'vc-hg-resolve-when-done nil t)
- (message "There are unresolved conflicts in this file")))
+ (vc-message-unresolved-conflicts buffer-file-name)))
;; Modeled after the similar function in vc-bzr.el
;; use conflict markers in which case we don't really know what to do.
;; So let's just punt for now.
nil)
- (message "There are unresolved conflicts in this file")))
+ (vc-message-unresolved-conflicts buffer-file-name)))
(defun vc-svn-parse-status (&optional filename)
"Parse output of \"svn status\" command in the current buffer.
(smerge-mode 1)
(message "File contains conflicts.")))
+;;;###autoload
+(defun vc-message-unresolved-conflicts (filename)
+ "Display a message indicating unresolved conflicts in FILENAME."
+ ;; This enables all VC backends to give a standard, recognizeable
+ ;; conflict message that indicates which file is conflicted.
+ (message "There are unresolved conflicts in %s" filename))
+
;;;###autoload
(defalias 'vc-resolve-conflicts 'smerge-ediff)
xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size)
{
eassert (0 <= nitems && 0 < item_size);
- if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
+ ptrdiff_t nbytes;
+ if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes)
memory_full (SIZE_MAX);
- return xmalloc (nitems * item_size);
+ return xmalloc (nbytes);
}
xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
{
eassert (0 <= nitems && 0 < item_size);
- if (min (PTRDIFF_MAX, SIZE_MAX) / item_size < nitems)
+ ptrdiff_t nbytes;
+ if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes)
memory_full (SIZE_MAX);
- return xrealloc (pa, nitems * item_size);
+ return xrealloc (pa, nbytes);
}
xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
ptrdiff_t nitems_max, ptrdiff_t item_size)
{
+ ptrdiff_t n0 = *nitems;
+ eassume (0 < item_size && 0 < nitems_incr_min && 0 <= n0 && -1 <= nitems_max);
+
/* The approximate size to use for initial small allocation
requests. This is the largest "small" request for the GNU C
library malloc. */
enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
/* If the array is tiny, grow it to about (but no greater than)
- DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%. */
- ptrdiff_t n = *nitems;
- ptrdiff_t tiny_max = DEFAULT_MXFAST / item_size - n;
- ptrdiff_t half_again = n >> 1;
- ptrdiff_t incr_estimate = max (tiny_max, half_again);
-
- /* Adjust the increment according to three constraints: NITEMS_INCR_MIN,
+ DEFAULT_MXFAST bytes. Otherwise, grow it by about 50%.
+ Adjust the growth according to three constraints: NITEMS_INCR_MIN,
NITEMS_MAX, and what the C language can represent safely. */
- ptrdiff_t C_language_max = min (PTRDIFF_MAX, SIZE_MAX) / item_size;
- ptrdiff_t n_max = (0 <= nitems_max && nitems_max < C_language_max
- ? nitems_max : C_language_max);
- ptrdiff_t nitems_incr_max = n_max - n;
- ptrdiff_t incr = max (nitems_incr_min, min (incr_estimate, nitems_incr_max));
- eassert (0 < item_size && 0 < nitems_incr_min && 0 <= n && -1 <= nitems_max);
+ ptrdiff_t n, nbytes;
+ if (INT_ADD_WRAPV (n0, n0 >> 1, &n))
+ n = PTRDIFF_MAX;
+ if (0 <= nitems_max && nitems_max < n)
+ n = nitems_max;
+
+ ptrdiff_t adjusted_nbytes
+ = ((INT_MULTIPLY_WRAPV (n, item_size, &nbytes) || SIZE_MAX < nbytes)
+ ? min (PTRDIFF_MAX, SIZE_MAX)
+ : nbytes < DEFAULT_MXFAST ? DEFAULT_MXFAST : 0);
+ if (adjusted_nbytes)
+ {
+ n = adjusted_nbytes / item_size;
+ nbytes = adjusted_nbytes - adjusted_nbytes % item_size;
+ }
+
if (! pa)
*nitems = 0;
- if (nitems_incr_max < incr)
+ if (n - n0 < nitems_incr_min
+ && (INT_ADD_WRAPV (n0, nitems_incr_min, &n)
+ || (0 <= nitems_max && nitems_max < n)
+ || INT_MULTIPLY_WRAPV (n, item_size, &nbytes)))
memory_full (SIZE_MAX);
- n += incr;
- pa = xrealloc (pa, n * item_size);
+ pa = xrealloc (pa, nbytes);
*nitems = n;
return pa;
}
EMACS_INT string_len = XINT (length);
unsigned char *p, *beg, *end;
- if (string_len > STRING_BYTES_MAX / len)
+ if (INT_MULTIPLY_WRAPV (len, string_len, &nbytes))
string_overflow ();
- nbytes = len * string_len;
val = make_uninit_multibyte_string (string_len, nbytes);
for (beg = SDATA (val), p = beg, end = beg + nbytes; p < end; p += len)
{
are not marked too. But we must be sure that nothing is
marked within OBJ before we really drop it. */
for (i = 0; i < size; i++)
- if (VECTOR_MARKED_P (XFONT_ENTITY (AREF (XCDR (obj), i))))
- break;
+ {
+ Lisp_Object objlist;
+
+ if (VECTOR_MARKED_P (XFONT_ENTITY (AREF (XCDR (obj), i))))
+ break;
+
+ objlist = AREF (AREF (XCDR (obj), i), FONT_OBJLIST_INDEX);
+ for (; CONSP (objlist); objlist = XCDR (objlist))
+ {
+ Lisp_Object val = XCAR (objlist);
+ struct font *font = XFONT_OBJECT (val);
+
+ if (!NILP (AREF (val, FONT_TYPE_INDEX))
+ && VECTOR_MARKED_P(font))
+ break;
+ }
+ if (CONSP (objlist))
+ {
+ /* Foiund a marked font, bail out. */
+ break;
+ }
+ }
if (i == size)
- drop = 1;
+ {
+ /* No marked fonts were found, so this entire font
+ entity can be dropped. */
+ drop = 1;
+ }
}
if (drop)
*prev = XCDR (tail);
else
nbytes = SBYTES (str);
- if (INT_ADD_OVERFLOW (ssl->bytes, nbytes))
+ if (INT_ADD_WRAPV (ssl->bytes, nbytes, &nbytes))
memory_full (SIZE_MAX);
- ssl->bytes += nbytes;
+ ssl->bytes = nbytes;
if (STRINGP (str2))
{
else
nbytes = SBYTES (str2);
- if (INT_ADD_OVERFLOW (ssl->bytes, nbytes))
+ if (INT_ADD_WRAPV (ssl->bytes, nbytes, &nbytes))
memory_full (SIZE_MAX);
- ssl->bytes += nbytes;
+ ssl->bytes = nbytes;
}
}
unsigned char *p;
ptrdiff_t total;
- if (INT_ADD_OVERFLOW (overlay_heads.bytes, overlay_tails.bytes))
+ if (INT_ADD_WRAPV (overlay_heads.bytes, overlay_tails.bytes, &total))
memory_full (SIZE_MAX);
- total = overlay_heads.bytes + overlay_tails.bytes;
if (total > overlay_str_len)
overlay_str_buf = xpalloc (overlay_str_buf, &overlay_str_len,
total - overlay_str_len, -1, 1);
Lisp_Object *copy;
ptrdiff_t i;
+ if (size)
+ {
+ Lisp_Object ovl
+ = XVECTOR (last_overlay_modification_hooks)->contents[1];
+
+ /* If the buffer of the first overlay in the array doesn't
+ match the current buffer, then these modification hooks
+ should not be run in this buffer. This could happen when
+ some code calls some insdel functions, such as del_range_1,
+ with the PREPARE argument false -- in that case this
+ function is never called to record the overlay modification
+ hook functions in the last_overlay_modification_hooks
+ array, so anything we find there is not ours. */
+ if (XMARKER (OVERLAY_START (ovl))->buffer != current_buffer)
+ return;
+ }
+
USE_SAFE_ALLOCA;
SAFE_ALLOCA_LISP (copy, size);
memcpy (copy, XVECTOR (last_overlay_modification_hooks)->contents,
ptrdiff_t i, i_byte, size = SCHARS (obj);
int len;
USE_SAFE_ALLOCA;
- ptrdiff_t o_size = (size < STRING_BYTES_BOUND / MAX_MULTIBYTE_LENGTH
- ? size * MAX_MULTIBYTE_LENGTH
- : STRING_BYTES_BOUND);
+ ptrdiff_t o_size;
+ if (INT_MULTIPLY_WRAPV (size, MAX_MULTIBYTE_LENGTH, &o_size))
+ o_size = PTRDIFF_MAX;
unsigned char *dst = SAFE_ALLOCA (o_size);
unsigned char *o = dst;
for (i = i_byte = 0; i < size; i++, i_byte += len)
{
- if (o_size - (o - dst) < MAX_MULTIBYTE_LENGTH)
+ if (o_size - MAX_MULTIBYTE_LENGTH < o - dst)
string_overflow ();
c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, len);
if (inword && flag != CASE_CAPITALIZE_UP)
}
buf_magnification = ccl.buf_magnification ? ccl.buf_magnification : 1;
-
- if ((min (PTRDIFF_MAX, SIZE_MAX) - 256) / buf_magnification < str_bytes)
+ outbufsize = str_bytes;
+ if (INT_MULTIPLY_WRAPV (buf_magnification, outbufsize, &outbufsize)
+ || INT_ADD_WRAPV (256, outbufsize, &outbufsize))
memory_full (SIZE_MAX);
- outbufsize = (ccl.buf_magnification
- ? str_bytes * ccl.buf_magnification + 256
- : str_bytes + 256);
outp = outbuf = xmalloc (outbufsize);
consumed_chars = consumed_bytes = 0;
/* At first, see the document in `character.h' to understand the code
in this file. */
-#ifdef emacs
#include <config.h>
-#endif
#include <stdio.h>
-#ifdef emacs
-
#include <sys/types.h>
#include <intprops.h>
#include "lisp.h"
#include "composite.h"
#include "disptab.h"
-#else /* not emacs */
-
-#include "mulelib.h"
-
-#endif /* emacs */
-
/* Char-table of information about which character to unify to which
Unicode character. Mainly used by the macro MAYBE_UNIFY_CHAR. */
Lisp_Object Vchar_unify_table;
if (CHARACTERP (ch))
{
int w = CHAR_WIDTH (XFASTINT (ch));
- if (INT_ADD_OVERFLOW (width, w))
+ if (INT_ADD_WRAPV (width, w, &width))
string_overflow ();
- width += w;
}
}
}
int c = STRING_CHAR_AND_LENGTH (str + i_byte, bytes);
ptrdiff_t thiswidth = char_width (c, dp);
- if (precision <= 0)
- {
- if (INT_ADD_OVERFLOW (width, thiswidth))
- string_overflow ();
- }
- else if (precision - width < thiswidth)
+ if (0 < precision && precision - width < thiswidth)
{
*nchars = i;
*nbytes = i_byte;
return width;
}
+ if (INT_ADD_WRAPV (thiswidth, width, &width))
+ string_overflow ();
i++;
i_byte += bytes;
- width += thiswidth;
}
if (precision > 0)
thiswidth = char_width (c, dp);
}
- if (precision <= 0)
- {
-#ifdef emacs
- if (INT_ADD_OVERFLOW (width, thiswidth))
- string_overflow ();
-#endif
- }
- else if (precision - width < thiswidth)
+ if (0 < precision && precision - width < thiswidth)
{
*nchars = i;
*nbytes = i_byte;
return width;
}
+ if (INT_ADD_WRAPV (thiswidth, width, &width))
+ string_overflow ();
i += chars;
i_byte += bytes;
- width += thiswidth;
}
if (precision > 0)
for (bytes = 0; str < endp; str++)
{
int n = *str < 0x80 ? 1 : 2;
- if (INT_ADD_OVERFLOW (bytes, n))
+ if (INT_ADD_WRAPV (bytes, n, &bytes))
string_overflow ();
- bytes += n;
}
return bytes;
}
ptrdiff_t nbytes = SBYTES (string);
bool multibyte = STRING_MULTIBYTE (string);
ptrdiff_t byte8_count;
+ ptrdiff_t thrice_byte8_count, uninit_nchars, uninit_nbytes;
const unsigned char *src, *src_end;
unsigned char *dst;
Lisp_Object val;
if (byte8_count == 0)
return string;
+ if (INT_MULTIPLY_WRAPV (byte8_count, 3, &thrice_byte8_count))
+ string_overflow ();
+
if (multibyte)
{
- if ((MOST_POSITIVE_FIXNUM - nchars) / 3 < byte8_count
- || (STRING_BYTES_BOUND - nbytes) / 2 < byte8_count)
- string_overflow ();
-
/* Convert 2-byte sequence of byte8 chars to 4-byte octal. */
- val = make_uninit_multibyte_string (nchars + byte8_count * 3,
- nbytes + byte8_count * 2);
+ if (INT_ADD_WRAPV (nchars, thrice_byte8_count, &uninit_nchars)
+ || INT_ADD_WRAPV (nbytes, 2 * byte8_count, &uninit_nbytes))
+ string_overflow ();
+ val = make_uninit_multibyte_string (uninit_nchars, uninit_nbytes);
}
else
{
- if ((STRING_BYTES_BOUND - nbytes) / 3 < byte8_count)
- string_overflow ();
-
/* Convert 1-byte sequence of byte8 chars to 4-byte octal. */
- val = make_uninit_string (nbytes + byte8_count * 3);
+ if (INT_ADD_WRAPV (thrice_byte8_count, nbytes, &uninit_nbytes))
+ string_overflow ();
+ val = make_uninit_string (uninit_nbytes);
}
src = SDATA (string);
return make_number (c);
}
-#ifdef emacs
-
/* Return true if C is an alphabetic character. */
bool
alphabeticp (int c)
/* The correct char-table is setup in characters.el. */
Vunicode_category_table = Qnil;
}
-
-#endif /* emacs */
static void
coding_alloc_by_realloc (struct coding_system *coding, ptrdiff_t bytes)
{
- if (STRING_BYTES_BOUND - coding->dst_bytes < bytes)
+ ptrdiff_t newbytes;
+ if (INT_ADD_WRAPV (coding->dst_bytes, bytes, &newbytes)
+ || SIZE_MAX < newbytes)
string_overflow ();
- coding->destination = xrealloc (coding->destination,
- coding->dst_bytes + bytes);
- coding->dst_bytes += bytes;
+ coding->destination = xrealloc (coding->destination, newbytes);
+ coding->dst_bytes = newbytes;
}
static void
if ((dst_end - dst) / MAX_MULTIBYTE_LENGTH < to_nchars)
{
eassert (growable_destination (coding));
- if (((min (PTRDIFF_MAX, SIZE_MAX) - (buf_end - buf))
- / MAX_MULTIBYTE_LENGTH)
- < to_nchars)
+ ptrdiff_t dst_size;
+ if (INT_MULTIPLY_WRAPV (to_nchars, MAX_MULTIBYTE_LENGTH,
+ &dst_size)
+ || INT_ADD_WRAPV (buf_end - buf, dst_size, &dst_size))
memory_full (SIZE_MAX);
- dst = alloc_destination (coding,
- buf_end - buf
- + MAX_MULTIBYTE_LENGTH * to_nchars,
- dst);
+ dst = alloc_destination (coding, dst_size, dst);
if (EQ (coding->src_object, coding->dst_object))
{
coding_set_source (coding);
return;
}
+ maybe_set_redisplay (symbol);
sym = XSYMBOL (symbol);
start:
switch (code)
{
case Aadd:
- if (INT_ADD_OVERFLOW (accum, next))
- {
- overflow = 1;
- accum &= INTMASK;
- }
- accum += next;
+ overflow |= INT_ADD_WRAPV (accum, next, &accum);
break;
case Asub:
- if (INT_SUBTRACT_OVERFLOW (accum, next))
- {
- overflow = 1;
- accum &= INTMASK;
- }
- accum = argnum ? accum - next : nargs == 1 ? - next : next;
+ if (! argnum)
+ accum = nargs == 1 ? - next : next;
+ else
+ overflow |= INT_SUBTRACT_WRAPV (accum, next, &accum);
break;
case Amult:
- if (INT_MULTIPLY_OVERFLOW (accum, next))
- {
- EMACS_UINT a = accum, b = next, ab = a * b;
- overflow = 1;
- accum = ab & INTMASK;
- }
- else
- accum *= next;
+ overflow |= INT_MULTIPLY_WRAPV (accum, next, &accum);
break;
case Adiv:
if (! (argnum || nargs == 1))
{
if (next == 0)
xsignal0 (Qarith_error);
- accum /= next;
+ if (INT_DIVIDE_OVERFLOW (accum, next))
+ overflow = true;
+ else
+ accum /= next;
}
break;
case Alogand:
|| matrix_dim.width != pool->ncolumns);
/* Enlarge the glyph pool. */
- needed = matrix_dim.width;
- if (INT_MULTIPLY_OVERFLOW (needed, matrix_dim.height))
+ if (INT_MULTIPLY_WRAPV (matrix_dim.height, matrix_dim.width, &needed))
memory_full (SIZE_MAX);
- needed *= matrix_dim.height;
if (needed > pool->nglyphs)
{
ptrdiff_t old_nglyphs = pool->nglyphs;
if (FRAME_WINDOW_P (f))
{
- int ch_height = FRAME_SMALLEST_FONT_HEIGHT (f);
+ /* http://lists.gnu.org/archive/html/emacs-devel/2015-11/msg00194.html */
+ int ch_height = max (FRAME_SMALLEST_FONT_HEIGHT (f), 1);
int window_pixel_height = window_box_height (w) + eabs (w->vscroll);
return (((window_pixel_height + ch_height - 1)
struct frame *f = XFRAME (w->frame);
if (FRAME_WINDOW_P (f))
{
- int ch_width = FRAME_SMALLEST_CHAR_WIDTH (f);
+ /* http://lists.gnu.org/archive/html/emacs-devel/2015-11/msg00194.html */
+ int ch_width = max (FRAME_SMALLEST_CHAR_WIDTH (f), 1);
/* Compute number of glyphs needed in a glyph row. */
return (((WINDOW_PIXEL_WIDTH (w) + ch_width - 1)
struct frame *sf = SELECTED_FRAME ();
int width = FRAME_TOTAL_COLS (sf);
int height = FRAME_TOTAL_LINES (sf);
+ int area;
/* If these sizes are so big they cause overflow, just ignore the
change. It's not clear what better we could do. The rest of
the code assumes that (width + 2) * height * sizeof (struct glyph)
does not overflow and does not exceed PTRDIFF_MAX or SIZE_MAX. */
- if (INT_ADD_OVERFLOW (width, 2)
- || INT_MULTIPLY_OVERFLOW (width + 2, height)
- || (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph)
- < (width + 2) * height))
+ if (INT_ADD_WRAPV (width, 2, &area)
+ || INT_MULTIPLY_WRAPV (height, area, &area)
+ || min (PTRDIFF_MAX, SIZE_MAX) / sizeof (struct glyph) < area)
fatal ("screen size %dx%d too big", width, height);
}
ptrdiff_t formatlen = SBYTES (args[0]);
/* Allocate the info and discarded tables. */
- if ((SIZE_MAX - formatlen) / sizeof (struct info) <= nargs)
+ ptrdiff_t alloca_size;
+ if (INT_MULTIPLY_WRAPV (nargs, sizeof *info, &alloca_size)
+ || INT_ADD_WRAPV (sizeof *info, alloca_size, &alloca_size)
+ || INT_ADD_WRAPV (formatlen, alloca_size, &alloca_size)
+ || SIZE_MAX < alloca_size)
memory_full (SIZE_MAX);
- size_t alloca_size = (nargs + 1) * sizeof *info + formatlen;
/* info[0] is unused. Unused elements have -1 for start. */
info = SAFE_ALLOCA (alloca_size);
memset (info, 0, alloca_size);
unsigned char str[MAX_MULTIBYTE_LENGTH];
int len = CHAR_STRING (charval, str);
ptrdiff_t size_byte = SBYTES (array);
+ ptrdiff_t product;
- if (INT_MULTIPLY_OVERFLOW (SCHARS (array), len)
- || SCHARS (array) * len != size_byte)
+ if (INT_MULTIPLY_WRAPV (size, len, &product) || product != size_byte)
error ("Attempt to change byte length of a string");
for (idx = 0; idx < size_byte; idx++)
*p++ = str[idx % len];
}
}
- if (INT_MAX / 2 < len)
+ int len2;
+ if (INT_MULTIPLY_WRAPV (len, 2, &len2))
memory_full (SIZE_MAX);
if (gstring.allocated == 0)
{
gstring.glyph_size = sizeof (MFLTGlyphFT);
- gstring.glyphs = xnmalloc (len * 2, sizeof (MFLTGlyphFT));
- gstring.allocated = len * 2;
+ gstring.glyphs = xnmalloc (len2, sizeof (MFLTGlyphFT));
+ gstring.allocated = len2;
}
- else if (gstring.allocated < len * 2)
+ else if (gstring.allocated < len2)
{
- gstring.glyphs = xnrealloc (gstring.glyphs, len * 2,
+ gstring.glyphs = xnrealloc (gstring.glyphs, len2,
sizeof (MFLTGlyphFT));
- gstring.allocated = len * 2;
+ gstring.allocated = len2;
}
glyphs = (MFLTGlyphFT *) (gstring.glyphs);
memset (glyphs, 0, len * sizeof (MFLTGlyphFT));
int result = mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, flt);
if (result != -2)
break;
- if (INT_MAX / 2 < gstring.allocated)
+ int len2;
+ if (INT_MULTIPLY_WRAPV (gstring.allocated, 2, &len2))
memory_full (SIZE_MAX);
gstring.glyphs = xnrealloc (gstring.glyphs,
gstring.allocated, 2 * sizeof (MFLTGlyphFT));
- gstring.allocated *= 2;
+ gstring.allocated = len2;
}
if (gstring.used > LGSTRING_GLYPH_LEN (lgstring))
return Qnil;
gnutls_hex_string (unsigned char *buf, ptrdiff_t buf_size, const char *prefix)
{
ptrdiff_t prefix_length = strlen (prefix);
- if ((STRING_BYTES_BOUND - prefix_length) / 3 < buf_size)
+ ptrdiff_t retlen;
+ if (INT_MULTIPLY_WRAPV (buf_size, 3, &retlen)
+ || INT_ADD_WRAPV (prefix_length - (buf_size != 0), retlen, &retlen))
string_overflow ();
- Lisp_Object ret = make_uninit_string (prefix_length + 3 * buf_size
- - (buf_size != 0));
+ Lisp_Object ret = make_uninit_string (retlen);
char *string = SSDATA (ret);
strcpy (string, prefix);
if (cp) g_free (cp);
len = strlen (str);
- if ((min (PTRDIFF_MAX, SIZE_MAX) - len - 1) / 4 < nr_bad)
+ ptrdiff_t alloc;
+ if (INT_MULTIPLY_WRAPV (nr_bad, 4, &alloc)
+ || INT_ADD_WRAPV (len + 1, alloc, &alloc)
+ || SIZE_MAX < alloc)
memory_full (SIZE_MAX);
- up = utf8_str = xmalloc (len + nr_bad * 4 + 1);
+ up = utf8_str = xmalloc (alloc);
p = (unsigned char *)str;
while (! (cp = g_locale_to_utf8 ((char *)p, -1, &bytes_read,
int x, y;
XColor *colors, *p;
XImagePtr_or_DC ximg;
+ ptrdiff_t nbytes;
#ifdef HAVE_NTGUI
HGDIOBJ prev;
#endif /* HAVE_NTGUI */
- if (img->height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width)
+ if (INT_MULTIPLY_WRAPV (sizeof *colors, img->width, &nbytes)
+ || INT_MULTIPLY_WRAPV (img->height, nbytes, &nbytes)
+ || SIZE_MAX < nbytes)
memory_full (SIZE_MAX);
- colors = xmalloc (sizeof *colors * img->width * img->height);
+ colors = xmalloc (nbytes);
/* Get the X image or create a memory device context for IMG. */
ximg = image_get_x_image_or_dc (f, img, 0, &prev);
XColor *colors = x_to_xcolors (f, img, 1);
XColor *new, *p;
int x, y, i, sum;
+ ptrdiff_t nbytes;
for (i = sum = 0; i < 9; ++i)
sum += eabs (matrix[i]);
#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
- if (img->height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width)
+ if (INT_MULTIPLY_WRAPV (sizeof *new, img->width, &nbytes)
+ || INT_MULTIPLY_WRAPV (img->height, nbytes, &nbytes))
memory_full (SIZE_MAX);
- new = xmalloc (sizeof *new * img->width * img->height);
+ new = xmalloc (nbytes);
for (y = 0; y < img->height; ++y)
{
png_uint_32 row_bytes;
bool transparent_p;
struct png_memory_storage tbr; /* Data to be read */
+ ptrdiff_t nbytes;
#ifdef USE_CAIRO
unsigned char *data = 0;
row_bytes = png_get_rowbytes (png_ptr, info_ptr);
/* Allocate memory for the image. */
- if (height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows
- || row_bytes > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height)
+ if (INT_MULTIPLY_WRAPV (row_bytes, sizeof *pixels, &nbytes)
+ || INT_MULTIPLY_WRAPV (nbytes, height, &nbytes))
memory_full (SIZE_MAX);
- c->pixels = pixels = xmalloc (sizeof *pixels * row_bytes * height);
+ c->pixels = pixels = xmalloc (nbytes);
c->rows = rows = xmalloc (height * sizeof *rows);
for (i = 0; i < height; ++i)
rows[i] = pixels + i * row_bytes;
XSETCDR (elt, def);
return def;
}
- else if (CONSP (idx) && CHARACTERP (XCAR (idx)))
+ else if (CONSP (idx)
+ && CHARACTERP (XCAR (idx))
+ && CHARACTERP (XCAR (elt)))
{
int from = XFASTINT (XCAR (idx));
int to = XFASTINT (XCDR (idx));
size += XINT (Flength (prefix));
/* This has one extra element at the end that we don't pass to Fconcat. */
- if (min (PTRDIFF_MAX, SIZE_MAX) / word_size / 4 < size)
+ EMACS_INT size4;
+ if (INT_MULTIPLY_WRAPV (size, 4, &size4))
memory_full (SIZE_MAX);
- SAFE_ALLOCA_LISP (args, size * 4);
+ SAFE_ALLOCA_LISP (args, size4);
/* In effect, this computes
(mapconcat 'single-key-description keys " ")
} \
} while (false)
-
-/* Return floor (NBYTES / WORD_SIZE). */
-
-INLINE ptrdiff_t
-lisp_word_count (ptrdiff_t nbytes)
-{
- if (-1 >> 1 == -1)
- switch (word_size + 0)
- {
- case 2: return nbytes >> 1;
- case 4: return nbytes >> 2;
- case 8: return nbytes >> 3;
- case 16: return nbytes >> 4;
- default: break;
- }
- return nbytes / word_size - (nbytes % word_size < 0);
-}
-
/* SAFE_ALLOCA_LISP allocates an array of Lisp_Objects. */
#define SAFE_ALLOCA_LISP(buf, nelt) \
do { \
- if ((nelt) <= lisp_word_count (sa_avail)) \
- (buf) = AVAIL_ALLOCA ((nelt) * word_size); \
- else if ((nelt) <= min (PTRDIFF_MAX, SIZE_MAX) / word_size) \
+ ptrdiff_t alloca_nbytes; \
+ if (INT_MULTIPLY_WRAPV (nelt, word_size, &alloca_nbytes) \
+ || SIZE_MAX < alloca_nbytes) \
+ memory_full (SIZE_MAX); \
+ else if (alloca_nbytes <= sa_avail) \
+ (buf) = AVAIL_ALLOCA (alloca_nbytes); \
+ else \
{ \
Lisp_Object arg_; \
- (buf) = xmalloc ((nelt) * word_size); \
+ (buf) = xmalloc (alloca_nbytes); \
arg_ = make_save_memory (buf, nelt); \
sa_must_free = true; \
record_unwind_protect (free_save_value, arg_); \
} \
- else \
- memory_full (SIZE_MAX); \
} while (false)
static ptrdiff_t read_buffer_size;
static char *read_buffer;
+/* Grow the read buffer by at least MAX_MULTIBYTE_LENGTH bytes. */
+
+static void
+grow_read_buffer (void)
+{
+ read_buffer = xpalloc (read_buffer, &read_buffer_size,
+ MAX_MULTIBYTE_LENGTH, -1, 1);
+}
+
/* Read a \-escape sequence, assuming we already read the `\'.
If the escape sequence forces unibyte, return eight-bit char. */
if (end - p < MAX_MULTIBYTE_LENGTH)
{
ptrdiff_t offset = p - read_buffer;
- if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size)
- memory_full (SIZE_MAX);
- read_buffer = xrealloc (read_buffer, read_buffer_size * 2);
- read_buffer_size *= 2;
+ grow_read_buffer ();
p = read_buffer + offset;
end = read_buffer + read_buffer_size;
}
if (end - p < MAX_MULTIBYTE_LENGTH)
{
ptrdiff_t offset = p - read_buffer;
- if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size)
- memory_full (SIZE_MAX);
- read_buffer = xrealloc (read_buffer, read_buffer_size * 2);
- read_buffer_size *= 2;
+ grow_read_buffer ();
p = read_buffer + offset;
end = read_buffer + read_buffer_size;
}
if (p == end)
{
ptrdiff_t offset = p - read_buffer;
- if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < read_buffer_size)
- memory_full (SIZE_MAX);
- read_buffer = xrealloc (read_buffer, read_buffer_size * 2);
- read_buffer_size *= 2;
+ grow_read_buffer ();
p = read_buffer + offset;
end = read_buffer + read_buffer_size;
}
{
if (kb->kbd_macro_ptr - kb->kbd_macro_buffer == kb->kbd_macro_bufsize)
{
- ptrdiff_t ptr_offset, end_offset, nbytes;
-
- ptr_offset = kb->kbd_macro_ptr - kb->kbd_macro_buffer;
- end_offset = kb->kbd_macro_end - kb->kbd_macro_buffer;
- if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *kb->kbd_macro_buffer / 2
- < kb->kbd_macro_bufsize)
- memory_full (SIZE_MAX);
- nbytes = kb->kbd_macro_bufsize * (2 * sizeof *kb->kbd_macro_buffer);
- kb->kbd_macro_buffer = xrealloc (kb->kbd_macro_buffer, nbytes);
- kb->kbd_macro_bufsize *= 2;
+ ptrdiff_t ptr_offset = kb->kbd_macro_ptr - kb->kbd_macro_buffer;
+ ptrdiff_t end_offset = kb->kbd_macro_end - kb->kbd_macro_buffer;
+ kb->kbd_macro_buffer = xpalloc (kb->kbd_macro_buffer,
+ &kb->kbd_macro_bufsize,
+ 1, -1, sizeof *kb->kbd_macro_buffer);
kb->kbd_macro_ptr = kb->kbd_macro_buffer + ptr_offset;
kb->kbd_macro_end = kb->kbd_macro_buffer + end_offset;
}
if (hide_char)
fprintf (stdout, "%c", hide_char);
if (len == size)
- {
- if (STRING_BYTES_BOUND / 2 < size)
- memory_full (SIZE_MAX);
- size *= 2;
- line = xrealloc (line, size);
- }
+ line = xpalloc (line, &size, 1, -1, sizeof *line);
line[len++] = c;
}
}
static void
ns_constrain_all_frames (void)
+/* --------------------------------------------------------------------------
+ Ensure that the menu bar doesn't cover any frames.
+ -------------------------------------------------------------------------- */
{
Lisp_Object tail, frame;
struct frame *f = XFRAME (frame);
if (FRAME_NS_P (f))
{
- NSView *view = FRAME_NS_VIEW (f);
+ EmacsView *view = FRAME_NS_VIEW (f);
- [[view window] setFrame:constrain_frame_rect([[view window] frame])
- display:NO];
+ if (![view isFullscreen])
+ {
+ [[view window]
+ setFrame:constrain_frame_rect([[view window] frame])
+ display:NO];
+ }
}
}
}
-/* Show or hide the menu bar, based on user setting. */
-
static void
ns_update_auto_hide_menu_bar (void)
+/* --------------------------------------------------------------------------
+ Show or hide the menu bar, based on user setting.
+ -------------------------------------------------------------------------- */
{
#ifdef NS_IMPL_COCOA
NSTRACE ("ns_update_auto_hide_menu_bar");
wr = NSMakeRect (0, 0, neww, newh);
NSTRACE_RECT ("setFrame", wr);
[view setFrame: wr];
- [self windowDidMove:nil]; // Update top/left.
+ // to do: consider using [NSNotificationCenter postNotificationName:].
+ [self windowDidMove: // Update top/left.
+ [NSNotification notificationWithName:NSWindowDidMoveNotification
+ object:[view window]]];
}
else
{
- (void)windowDidResize: (NSNotification *)notification
{
NSTRACE ("windowDidResize");
-
+ if (!FRAME_LIVE_P (emacsframe))
+ {
+ NSTRACE_MSG ("Ignored (frame dead)");
+ return;
+ }
if (emacsframe->output_data.ns->in_animation)
{
NSTRACE_MSG ("Ignored (in animation)");
- (void)windowWillExitFullScreen:(NSNotification *)notification
{
NSTRACE ("windowWillExitFullScreen");
-
+ if (!FRAME_LIVE_P (emacsframe))
+ {
+ NSTRACE_MSG ("Ignored (frame dead)");
+ return;
+ }
if (next_maximized != -1)
fs_before_fs = next_maximized;
}
- (void)windowDidExitFullScreen:(NSNotification *)notification
{
NSTRACE ("windowDidExitFullScreen");
-
+ if (!FRAME_LIVE_P (emacsframe))
+ {
+ NSTRACE_MSG ("Ignored (frame dead)");
+ return;
+ }
[self setFSValue: fs_before_fs];
fs_before_fs = -1;
#ifdef HAVE_NATIVE_FS
nonfs_window = w;
- [self windowWillEnterFullScreen:nil];
+ [self windowWillEnterFullScreen:
+ [NSNotification notificationWithName:NSWindowWillEnterFullScreenNotification
+ object:[self window]]];
[fw makeKeyAndOrderFront:NSApp];
[fw makeFirstResponder:self];
[w orderOut:self];
r = [fw frameRectForContentRect:[screen frame]];
[fw setFrame: r display:YES animate:ns_use_fullscreen_animation];
- [self windowDidEnterFullScreen:nil];
+ [self windowDidEnterFullScreen:
+ [NSNotification notificationWithName:NSWindowDidEnterFullScreenNotification
+ object:[self window]]];
[fw display];
}
else
if (FRAME_EXTERNAL_TOOL_BAR (f))
FRAME_TOOLBAR_HEIGHT (f) = tobar_height;
- [self windowWillExitFullScreen:nil];
+ // to do: consider using [NSNotificationCenter postNotificationName:] to send notifications.
+
+ [self windowWillExitFullScreen:
+ [NSNotification notificationWithName:NSWindowWillExitFullScreenNotification
+ object:[self window]]];
[fw setFrame: [w frame] display:YES animate:ns_use_fullscreen_animation];
[fw close];
[w makeKeyAndOrderFront:NSApp];
- [self windowDidExitFullScreen:nil];
+ [self windowDidExitFullScreen:
+ [NSNotification notificationWithName:NSWindowDidExitFullScreenNotification
+ object:[self window]]];
[self updateFrameSize:YES];
}
}
multibyte-form. But, it may be enlarged on demand if
Vglyph_table contains a string or a composite glyph is
encountered. */
- if (min (PTRDIFF_MAX, SIZE_MAX) / MAX_MULTIBYTE_LENGTH < src_len)
+ if (INT_MULTIPLY_WRAPV (src_len, MAX_MULTIBYTE_LENGTH, &required))
memory_full (SIZE_MAX);
- required = src_len;
- required *= MAX_MULTIBYTE_LENGTH;
if (encode_terminal_src_size < required)
- {
- encode_terminal_src = xrealloc (encode_terminal_src, required);
- encode_terminal_src_size = required;
- }
+ encode_terminal_src = xpalloc (encode_terminal_src,
+ &encode_terminal_src_size,
+ required - encode_terminal_src_size,
+ -1, sizeof *encode_terminal_src);
charset_list = coding_charset_list (coding);
doup++, append_len_incr = strlen (up);
else
doleft++, append_len_incr = strlen (left);
- if (INT_ADD_OVERFLOW (append_len, append_len_incr))
+ if (INT_ADD_WRAPV (append_len_incr,
+ append_len, &append_len))
memory_full (SIZE_MAX);
- append_len += append_len_incr;
}
}
*op++ = tem ? tem : 0200;
* On some machines, an existing old_name file is required.
*
*/
-
-/* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
- * ELF support added.
- *
- * Basic theory: the data space of the running process needs to be
- * dumped to the output file. Normally we would just enlarge the size
- * of .data, scooting everything down. But we can't do that in ELF,
- * because there is often something between the .data space and the
- * .bss space.
- *
- * In the temacs dump below, notice that the Global Offset Table
- * (.got) and the Dynamic link data (.dynamic) come between .data1 and
- * .bss. It does not work to overlap .data with these fields.
- *
- * The solution is to create a new .data segment. This segment is
- * filled with data from the current process. Since the contents of
- * various sections refer to sections by index, the new .data segment
- * is made the last in the table to avoid changing any existing index.
-
- * This is an example of how the section headers are changed. "Addr"
- * is a process virtual address. "Offset" is a file offset.
-
-raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
-
-temacs:
-
- **** SECTION HEADER TABLE ****
- [No] Type Flags Addr Offset Size Name
- Link Info Adralgn Entsize
-
- [1] 1 2 0x80480d4 0xd4 0x13 .interp
- 0 0 0x1 0
-
- [2] 5 2 0x80480e8 0xe8 0x388 .hash
- 3 0 0x4 0x4
-
- [3] 11 2 0x8048470 0x470 0x7f0 .dynsym
- 4 1 0x4 0x10
-
- [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
- 0 0 0x1 0
-
- [5] 9 2 0x8049010 0x1010 0x338 .rel.plt
- 3 7 0x4 0x8
-
- [6] 1 6 0x8049348 0x1348 0x3 .init
- 0 0 0x4 0
-
- [7] 1 6 0x804934c 0x134c 0x680 .plt
- 0 0 0x4 0x4
-
- [8] 1 6 0x80499cc 0x19cc 0x3c56f .text
- 0 0 0x4 0
-
- [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
- 0 0 0x4 0
-
- [10] 1 2 0x8085f40 0x3df40 0x69c .rodata
- 0 0 0x4 0
-
- [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
- 0 0 0x4 0
-
- [12] 1 3 0x8088330 0x3f330 0x20afc .data
- 0 0 0x4 0
-
- [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
- 0 0 0x4 0
-
- [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
- 0 0 0x4 0x4
-
- [15] 6 3 0x80a9874 0x60874 0x80 .dynamic
- 4 0 0x4 0x8
-
- [16] 8 3 0x80a98f4 0x608f4 0x449c .bss
- 0 0 0x4 0
-
- [17] 2 0 0 0x608f4 0x9b90 .symtab
- 18 371 0x4 0x10
-
- [18] 3 0 0 0x6a484 0x8526 .strtab
- 0 0 0x1 0
-
- [19] 3 0 0 0x729aa 0x93 .shstrtab
- 0 0 0x1 0
-
- [20] 1 0 0 0x72a3d 0x68b7 .comment
- 0 0 0x1 0
-
- raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
-
- xemacs:
-
- **** SECTION HEADER TABLE ****
- [No] Type Flags Addr Offset Size Name
- Link Info Adralgn Entsize
-
- [1] 1 2 0x80480d4 0xd4 0x13 .interp
- 0 0 0x1 0
-
- [2] 5 2 0x80480e8 0xe8 0x388 .hash
- 3 0 0x4 0x4
-
- [3] 11 2 0x8048470 0x470 0x7f0 .dynsym
- 4 1 0x4 0x10
-
- [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
- 0 0 0x1 0
-
- [5] 9 2 0x8049010 0x1010 0x338 .rel.plt
- 3 7 0x4 0x8
-
- [6] 1 6 0x8049348 0x1348 0x3 .init
- 0 0 0x4 0
-
- [7] 1 6 0x804934c 0x134c 0x680 .plt
- 0 0 0x4 0x4
-
- [8] 1 6 0x80499cc 0x19cc 0x3c56f .text
- 0 0 0x4 0
-
- [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
- 0 0 0x4 0
-
- [10] 1 2 0x8085f40 0x3df40 0x69c .rodata
- 0 0 0x4 0
-
- [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
- 0 0 0x4 0
-
- [12] 1 3 0x8088330 0x3f330 0x20afc .data
- 0 0 0x4 0
-
- [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
- 0 0 0x4 0
-
- [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
- 0 0 0x4 0x4
-
- [15] 6 3 0x80a9874 0x60874 0x80 .dynamic
- 4 0 0x4 0x8
-
- [16] 8 3 0x80c6800 0x7d800 0 .bss
- 0 0 0x4 0
-
- [17] 2 0 0 0x7d800 0x9b90 .symtab
- 18 371 0x4 0x10
-
- [18] 3 0 0 0x87390 0x8526 .strtab
- 0 0 0x1 0
-
- [19] 3 0 0 0x8f8b6 0x93 .shstrtab
- 0 0 0x1 0
-
- [20] 1 0 0 0x8f949 0x68b7 .comment
- 0 0 0x1 0
-
- [21] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
- 0 0 0x4 0
-
- * This is an example of how the file header is changed. "Shoff" is
- * the section header offset within the file. Since that table is
- * after the new .data section, it is moved. "Shnum" is the number of
- * sections, which we increment.
- *
- * "Phoff" is the file offset to the program header. "Phentsize" and
- * "Shentsz" are the program and section header entries sizes respectively.
- * These can be larger than the apparent struct sizes.
-
- raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
-
- temacs:
-
- **** ELF HEADER ****
- Class Data Type Machine Version
- Entry Phoff Shoff Flags Ehsize
- Phentsize Phnum Shentsz Shnum Shstrndx
-
- 1 1 2 3 1
- 0x80499cc 0x34 0x792f4 0 0x34
- 0x20 5 0x28 21 19
-
- raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
-
- xemacs:
-
- **** ELF HEADER ****
- Class Data Type Machine Version
- Entry Phoff Shoff Flags Ehsize
- Phentsize Phnum Shentsz Shnum Shstrndx
-
- 1 1 2 3 1
- 0x80499cc 0x34 0x96200 0 0x34
- 0x20 5 0x28 22 19
-
- * These are the program headers. "Offset" is the file offset to the
- * segment. "Vaddr" is the memory load address. "Filesz" is the
- * segment size as it appears in the file, and "Memsz" is the size in
- * memory. Below, the third segment is the code and the fourth is the
- * data: the difference between Filesz and Memsz is .bss
-
- raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
-
- temacs:
- ***** PROGRAM EXECUTION HEADER *****
- Type Offset Vaddr Paddr
- Filesz Memsz Flags Align
-
- 6 0x34 0x8048034 0
- 0xa0 0xa0 5 0
-
- 3 0xd4 0 0
- 0x13 0 4 0
-
- 1 0x34 0x8048034 0
- 0x3f2f9 0x3f2f9 5 0x1000
-
- 1 0x3f330 0x8088330 0
- 0x215c4 0x25a60 7 0x1000
-
- 2 0x60874 0x80a9874 0
- 0x80 0 7 0
-
- raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
-
- xemacs:
- ***** PROGRAM EXECUTION HEADER *****
- Type Offset Vaddr Paddr
- Filesz Memsz Flags Align
-
- 6 0x34 0x8048034 0
- 0xa0 0xa0 5 0
-
- 3 0xd4 0 0
- 0x13 0 4 0
-
- 1 0x34 0x8048034 0
- 0x3f2f9 0x3f2f9 5 0x1000
-
- 1 0x3f330 0x8088330 0
- 0x3e4d0 0x3e4d0 7 0x1000
-
- 2 0x60874 0x80a9874 0
- 0x80 0 7 0
-
-
- */
-\f
-/* Modified by wtien@urbana.mcd.mot.com of Motorola Inc.
- *
- * The above mechanism does not work if the unexeced ELF file is being
- * re-layout by other applications (such as `strip'). All the applications
- * that re-layout the internal of ELF will layout all sections in ascending
- * order of their file offsets. After the re-layout, the data2 section will
- * still be the LAST section in the section header vector, but its file offset
- * is now being pushed far away down, and causes part of it not to be mapped
- * in (ie. not covered by the load segment entry in PHDR vector), therefore
- * causes the new binary to fail.
- *
- * The solution is to modify the unexec algorithm to insert the new data2
- * section header right before the new bss section header, so their file
- * offsets will be in the ascending order. Since some of the section's (all
- * sections AFTER the bss section) indexes are now changed, we also need to
- * modify some fields to make them point to the right sections. This is done
- * by macro PATCH_INDEX. All the fields that need to be patched are:
- *
- * 1. ELF header e_shstrndx field.
- * 2. section header sh_link and sh_info field.
- * 3. symbol table entry st_shndx field.
- *
- * The above example now should look like:
-
- **** SECTION HEADER TABLE ****
- [No] Type Flags Addr Offset Size Name
- Link Info Adralgn Entsize
-
- [1] 1 2 0x80480d4 0xd4 0x13 .interp
- 0 0 0x1 0
-
- [2] 5 2 0x80480e8 0xe8 0x388 .hash
- 3 0 0x4 0x4
-
- [3] 11 2 0x8048470 0x470 0x7f0 .dynsym
- 4 1 0x4 0x10
-
- [4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
- 0 0 0x1 0
-
- [5] 9 2 0x8049010 0x1010 0x338 .rel.plt
- 3 7 0x4 0x8
-
- [6] 1 6 0x8049348 0x1348 0x3 .init
- 0 0 0x4 0
-
- [7] 1 6 0x804934c 0x134c 0x680 .plt
- 0 0 0x4 0x4
-
- [8] 1 6 0x80499cc 0x19cc 0x3c56f .text
- 0 0 0x4 0
-
- [9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
- 0 0 0x4 0
-
- [10] 1 2 0x8085f40 0x3df40 0x69c .rodata
- 0 0 0x4 0
-
- [11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
- 0 0 0x4 0
-
- [12] 1 3 0x8088330 0x3f330 0x20afc .data
- 0 0 0x4 0
-
- [13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
- 0 0 0x4 0
-
- [14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
- 0 0 0x4 0x4
-
- [15] 6 3 0x80a9874 0x60874 0x80 .dynamic
- 4 0 0x4 0x8
-
- [16] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
- 0 0 0x4 0
-
- [17] 8 3 0x80c6800 0x7d800 0 .bss
- 0 0 0x4 0
-
- [18] 2 0 0 0x7d800 0x9b90 .symtab
- 19 371 0x4 0x10
-
- [19] 3 0 0 0x87390 0x8526 .strtab
- 0 0 0x1 0
-
- [20] 3 0 0 0x8f8b6 0x93 .shstrtab
- 0 0 0x1 0
-
- [21] 1 0 0 0x8f949 0x68b7 .comment
- 0 0 0x1 0
-
- */
\f
/* We do not use mmap because that fails with NFS.
Instead we read the whole file, modify it, and write it out. */
/* Get the address of a particular section or program header entry,
* accounting for the size of the entries.
*/
-/*
- On PPC Reference Platform running Solaris 2.5.1
- the plt section is also of type NOBI like the bss section.
- (not really stored) and therefore sections after the bss
- section start at the plt offset. The plt section is always
- the one just before the bss section.
- Thus, we modify the test from
- if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
- to
- if (NEW_SECTION_H (nn).sh_offset >=
- OLD_SECTION_H (old_bss_index-1).sh_offset)
- This is just a hack. We should put the new data section
- before the .plt section.
- And we should not have this routine at all but use
- the libelf library to read the old file and create the new
- file.
- The changed code is minimal and depends on prep set in m/prep.h
- Erik Deumens
- Quantum Theory Project
- University of Florida
- deumens@qtp.ufl.edu
- Apr 23, 1996
- */
static void *
entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
(*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize))
#define NEW_SECTION_H(n) \
(*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize))
-#define NEW_PROGRAM_H(n) \
- (*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phentsize))
+#define OLD_PROGRAM_H(n) \
+ (*(ElfW (Phdr) *) entry_address (old_program_h, n, old_file_h->e_phentsize))
-#define PATCH_INDEX(n) ((n) += old_bss_index <= (n))
typedef unsigned char byte;
-/* Round X up to a multiple of Y. */
-
-static ElfW (Addr)
-round_up (ElfW (Addr) x, ElfW (Addr) y)
-{
- ElfW (Addr) rem = x % y;
- if (rem == 0)
- return x;
- return x - rem + y;
-}
-
-/* Return the index of the section named NAME.
- SECTION_NAMES, FILE_NAME and FILE_H give information
- about the file we are looking in.
-
- If we don't find the section NAME, that is a fatal error
- if NOERROR is false; return -1 if NOERROR is true. */
-
-static ptrdiff_t
-find_section (const char *name, const char *section_names, const char *file_name,
- ElfW (Ehdr) *old_file_h, ElfW (Shdr) *old_section_h,
- bool noerror)
-{
- ptrdiff_t idx;
-
- for (idx = 1; idx < old_file_h->e_shnum; idx++)
- {
- char const *found_name = section_names + OLD_SECTION_H (idx).sh_name;
-#ifdef UNEXELF_DEBUG
- fprintf (stderr, "Looking for %s - found %s\n", name, found_name);
-#endif
- if (strcmp (name, found_name) == 0)
- return idx;
- }
-
- if (! noerror)
- fatal ("Can't find %s in %s", name, file_name);
- return -1;
-}
-
/* ****************************************************************
* unexec
*
* driving logic.
*
- * In ELF, this works by replacing the old .bss section with a new
- * .data section, and inserting an empty .bss immediately afterwards.
+ * In ELF, this works by replacing the old bss SHT_NOBITS section with
+ * a new, larger, SHT_PROGBITS section.
*
*/
void
ElfW (Phdr) *old_program_h, *new_program_h;
ElfW (Shdr) *old_section_h, *new_section_h;
- /* Point to the section name table in the old file. */
- char *old_section_names;
+ /* Point to the section name table. */
+ char *old_section_names, *new_section_names;
+ ElfW (Phdr) *old_bss_seg, *new_bss_seg;
ElfW (Addr) old_bss_addr, new_bss_addr;
ElfW (Word) old_bss_size, new_data2_size;
- ElfW (Off) new_data2_offset;
- ElfW (Addr) new_data2_addr;
- ElfW (Off) old_bss_offset;
- ElfW (Word) new_data2_incr;
-
- ptrdiff_t n, nn;
- ptrdiff_t old_bss_index, old_sbss_index, old_plt_index;
- ptrdiff_t old_data_index, new_data2_index;
-#if defined _SYSTYPE_SYSV || defined __sgi
- ptrdiff_t old_mdebug_index;
-#endif
+ ElfW (Off) old_bss_offset, new_data2_offset;
+
+ ptrdiff_t n;
+ ptrdiff_t old_bss_index;
struct stat stat_buf;
off_t old_file_size;
old_section_names = (char *) old_base
+ OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
- /* Find the mdebug section, if any. */
-
-#if defined _SYSTYPE_SYSV || defined __sgi
- old_mdebug_index = find_section (".mdebug", old_section_names,
- old_name, old_file_h, old_section_h, 1);
-#endif
-
- /* Find the old .bss section. Figure out parameters of the new
- data2 and bss sections. */
-
- old_bss_index = find_section (".bss", old_section_names,
- old_name, old_file_h, old_section_h, 0);
-
- old_sbss_index = find_section (".sbss", old_section_names,
- old_name, old_file_h, old_section_h, 1);
- if (old_sbss_index != -1)
- if (OLD_SECTION_H (old_sbss_index).sh_type != SHT_NOBITS)
- old_sbss_index = -1;
-
- /* PowerPC64 has .plt in the BSS section. */
- old_plt_index = find_section (".plt", old_section_names,
- old_name, old_file_h, old_section_h, 1);
- if (old_plt_index != -1)
- if (OLD_SECTION_H (old_plt_index).sh_type != SHT_NOBITS)
- old_plt_index = -1;
-
- if (old_sbss_index == -1 && old_plt_index == -1)
- {
- old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
- old_bss_offset = OLD_SECTION_H (old_bss_index).sh_offset;
- new_data2_index = old_bss_index;
- }
- else if (old_plt_index != -1
- && (old_sbss_index == -1
- || (OLD_SECTION_H (old_sbss_index).sh_addr
- > OLD_SECTION_H (old_plt_index).sh_addr)))
+ /* Find the PT_LOAD header covering the highest address. This
+ segment will be where bss sections are located, past p_filesz. */
+ old_bss_seg = 0;
+ for (n = old_file_h->e_phnum; --n >= 0; )
{
- old_bss_addr = OLD_SECTION_H (old_plt_index).sh_addr;
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
- + OLD_SECTION_H (old_plt_index).sh_size;
- if (old_sbss_index != -1)
- old_bss_size += OLD_SECTION_H (old_sbss_index).sh_size;
- old_bss_offset = OLD_SECTION_H (old_plt_index).sh_offset;
- new_data2_index = old_plt_index;
+ ElfW (Phdr) *seg = &OLD_PROGRAM_H (n);
+ if (seg->p_type == PT_LOAD
+ && (old_bss_seg == 0
+ || seg->p_vaddr > old_bss_seg->p_vaddr))
+ old_bss_seg = seg;
}
- else
+
+ /* Note that old_bss_addr may be lower than the first bss section
+ address, since the section may need aligning. */
+ old_bss_addr = old_bss_seg->p_vaddr + old_bss_seg->p_filesz;
+ old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz;
+ old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz;
+
+ /* Find the last bss style section in the bss segment range. */
+ old_bss_index = -1;
+ for (n = old_file_h->e_shnum; --n > 0; )
{
- old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr;
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
- + OLD_SECTION_H (old_sbss_index).sh_size;
- old_bss_offset = OLD_SECTION_H (old_sbss_index).sh_offset;
- new_data2_index = old_sbss_index;
+ ElfW (Shdr) *shdr = &OLD_SECTION_H (n);
+ if (shdr->sh_type == SHT_NOBITS
+ && shdr->sh_addr >= old_bss_addr
+ && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size
+ && (old_bss_index == -1
+ || OLD_SECTION_H (old_bss_index).sh_addr < shdr->sh_addr))
+ old_bss_index = n;
}
- /* Find the old .data section. Figure out parameters of
- the new data2 and bss sections. */
-
- old_data_index = find_section (".data", old_section_names,
- old_name, old_file_h, old_section_h, 0);
+ if (old_bss_index == -1)
+ fatal ("no bss section found");
new_break = sbrk (0);
new_bss_addr = (ElfW (Addr)) new_break;
- new_data2_addr = old_bss_addr;
new_data2_size = new_bss_addr - old_bss_addr;
- new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset
- + (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
- /* This is the amount by which the sections following the bss sections
- must be shifted in the image. It can differ from new_data2_size if
- the end of the old .data section (and thus the offset of the .bss
- section) was unaligned. */
- new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset);
+ new_data2_offset = old_bss_offset;
#ifdef UNEXELF_DEBUG
fprintf (stderr, "old_bss_index %td\n", old_bss_index);
DEBUG_LOG (old_bss_size);
DEBUG_LOG (old_bss_offset);
DEBUG_LOG (new_bss_addr);
- DEBUG_LOG (new_data2_addr);
DEBUG_LOG (new_data2_size);
DEBUG_LOG (new_data2_offset);
- DEBUG_LOG (new_data2_incr);
#endif
if (new_bss_addr < old_bss_addr + old_bss_size)
if (new_file < 0)
fatal ("Can't creat (%s): %s", new_name, strerror (errno));
- new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_incr;
+ new_file_size = old_file_size + new_data2_size;
if (ftruncate (new_file, new_file_size))
fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
if (new_base == MAP_FAILED)
fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
- new_file_h = (ElfW (Ehdr) *) new_base;
- new_program_h = (ElfW (Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
- new_section_h = (ElfW (Shdr) *)
- ((byte *) new_base + old_file_h->e_shoff + new_data2_incr);
-
/* Make our new file, program and section headers as copies of the
originals. */
+ new_file_h = (ElfW (Ehdr) *) new_base;
memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
- memcpy (new_program_h, old_program_h,
- old_file_h->e_phnum * old_file_h->e_phentsize);
- /* Modify the e_shstrndx if necessary. */
- PATCH_INDEX (new_file_h->e_shstrndx);
+ /* Fix up file header. Section header is further away now. */
+
+ if (new_file_h->e_shoff >= old_bss_offset)
+ new_file_h->e_shoff += new_data2_size;
- /* Fix up file header. We'll add one section. Section header is
- further away now. */
+ new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff);
+ new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff);
- new_file_h->e_shoff += new_data2_incr;
- new_file_h->e_shnum += 1;
+ memcpy (new_program_h, old_program_h,
+ old_file_h->e_phnum * old_file_h->e_phentsize);
+ memcpy (new_section_h, old_section_h,
+ old_file_h->e_shnum * old_file_h->e_shentsize);
#ifdef UNEXELF_DEBUG
DEBUG_LOG (old_file_h->e_shoff);
fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum);
#endif
- /* Fix up a new program header. Extend the writable data segment so
- that the bss area is covered too. Find that segment by looking
- for a segment that ends just before the .bss area. Make sure
- that no segments are above the new .data2. Put a loop at the end
- to adjust the offset and address of any segment that is above
- data2, just in case we decide to allow this later. */
-
- for (n = new_file_h->e_phnum; --n >= 0; )
- {
- /* Compute maximum of all requirements for alignment of section. */
- ElfW (Word) alignment = (NEW_PROGRAM_H (n)).p_align;
- if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
- alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
-
-#ifdef __sgi
- /* According to r02kar@x4u2.desy.de (Karsten Kuenne)
- and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we
- always get "Program segment above .bss" when dumping
- when the executable doesn't have an sbss section. */
- if (old_sbss_index != -1)
-#endif /* __sgi */
- if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz
- > (old_sbss_index == -1
- ? old_bss_addr
- : round_up (old_bss_addr, alignment)))
- fatal ("Program segment above .bss in %s", old_name);
-
- if (NEW_PROGRAM_H (n).p_type == PT_LOAD
- && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
- + (NEW_PROGRAM_H (n)).p_filesz,
- alignment)
- == round_up (old_bss_addr, alignment)))
- break;
- }
- if (n < 0)
- fatal ("Couldn't find segment next to .bss in %s", old_name);
-
- /* Make sure that the size includes any padding before the old .bss
- section. */
- NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr;
- NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
+ /* Fix up program header. Extend the writable data segment so
+ that the bss area is covered too. */
-#if 0 /* Maybe allow section after data2 - does this ever happen? */
- for (n = new_file_h->e_phnum; --n >= 0; )
- {
- if (NEW_PROGRAM_H (n).p_vaddr
- && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
- NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
-
- if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
- NEW_PROGRAM_H (n).p_offset += new_data2_incr;
- }
-#endif
+ new_bss_seg = new_program_h + (old_bss_seg - old_program_h);
+ new_bss_seg->p_filesz = new_bss_addr - new_bss_seg->p_vaddr;
+ new_bss_seg->p_memsz = new_bss_seg->p_filesz;
- /* Fix up section headers based on new .data2 section. Any section
- whose offset or virtual address is after the new .data2 section
- gets its value adjusted. .bss size becomes zero and new address
- is set. data2 section header gets added by copying the existing
- .data header and modifying the offset, address and size. */
+ /* Copy over what we have in memory now for the bss area. */
+ memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr, new_data2_size);
- /* Walk through all section headers, insert the new data2 section right
- before the new bss section. */
- for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
+ /* Walk through all section headers, copying data and updating. */
+ for (n = 1; n < old_file_h->e_shnum; n++)
{
caddr_t src;
- /* If it is (s)bss section, insert the new data2 section before it. */
- /* new_data2_index is the index of either old_sbss or old_bss, that was
- chosen as a section for new_data2. */
- if (n == new_data2_index)
- {
- /* Steal the data section header for this data2 section. */
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
- new_file_h->e_shentsize);
-
- NEW_SECTION_H (nn).sh_addr = new_data2_addr;
- NEW_SECTION_H (nn).sh_offset = new_data2_offset;
- NEW_SECTION_H (nn).sh_size = new_data2_size;
- /* Use the bss section's alignment. This will assure that the
- new data2 section always be placed in the same spot as the old
- bss section by any other application. */
- NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign;
-
- /* Now copy over what we have in the memory now. */
- memcpy (NEW_SECTION_H (nn).sh_offset + new_base,
- (caddr_t) OLD_SECTION_H (n).sh_addr,
- new_data2_size);
- nn++;
- }
+ ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
+ ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
- old_file_h->e_shentsize);
-
- if (n == old_bss_index
- /* The new bss and sbss section's size is zero, and its file offset
- and virtual address should be off by NEW_DATA2_SIZE. */
- || n == old_sbss_index || n == old_plt_index
- )
- {
- /* NN should be `old_s?bss_index + 1' at this point. */
- NEW_SECTION_H (nn).sh_offset = new_data2_offset + new_data2_size;
- NEW_SECTION_H (nn).sh_addr = new_data2_addr + new_data2_size;
- /* Let the new bss section address alignment be the same as the
- section address alignment followed the old bss section, so
- this section will be placed in exactly the same place. */
- NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
- NEW_SECTION_H (nn).sh_size = 0;
- }
- else
+ if (new_shdr->sh_type == SHT_NOBITS
+ && new_shdr->sh_addr >= old_bss_addr
+ && (new_shdr->sh_addr + new_shdr->sh_size
+ <= old_bss_addr + old_bss_size))
{
- /* Any section that was originally placed after the .bss
- section should now be off by NEW_DATA2_INCR. If a
- section overlaps the .bss section, consider it to be
- placed after the .bss section. Overlap can occur if the
- section just before .bss has less-strict alignment; this
- was observed between .symtab and .bss on Solaris 2.5.1
- (sparc) with GCC snapshot 960602.
-
-> dump -h temacs
-
-temacs:
-
- **** SECTION HEADER TABLE ****
-[No] Type Flags Addr Offset Size Name
- Link Info Adralgn Entsize
-
-[22] 1 3 0x335150 0x315150 0x4 .data.rel.local
- 0 0 0x4 0
-
-[23] 8 3 0x335158 0x315158 0x42720 .bss
- 0 0 0x8 0
-
-[24] 2 0 0 0x315154 0x1c9d0 .symtab
- 25 1709 0x4 0x10
- */
-
- if (NEW_SECTION_H (nn).sh_offset >= old_bss_offset
- || (NEW_SECTION_H (nn).sh_offset + NEW_SECTION_H (nn).sh_size
- > new_data2_offset))
- NEW_SECTION_H (nn).sh_offset += new_data2_incr;
-
- /* Any section that was originally placed after the section
- header table should now be off by the size of one section
- header table entry. */
- if (NEW_SECTION_H (nn).sh_offset > new_file_h->e_shoff)
- NEW_SECTION_H (nn).sh_offset += new_file_h->e_shentsize;
+ /* This section now has file backing. */
+ new_shdr->sh_type = SHT_PROGBITS;
+
+ /* SHT_NOBITS sections do not need a valid sh_offset, so it
+ might be incorrect. Write the correct value. */
+ new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
+ + new_bss_seg->p_offset);
+
+ /* If this is was a SHT_NOBITS .plt section, then it is
+ probably a PowerPC PLT. If it is PowerPC64 ELFv1 then
+ glibc ld.so doesn't initialize the toc pointer word. A
+ non-zero toc pointer word can defeat Power7 thread safety
+ during lazy update of a PLT entry. This only matters if
+ emacs becomes multi-threaded. */
+ if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0)
+ memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size);
+
+ /* Extend the size of the last bss section to cover dumped
+ data. */
+ if (n == old_bss_index)
+ new_shdr->sh_size = new_bss_addr - new_shdr->sh_addr;
+
+ /* We have already copied this section from the current
+ process. */
+ continue;
}
- /* If any section hdr refers to the section after the new .data
- section, make it refer to next one because we have inserted
- a new section in between. */
-
- PATCH_INDEX (NEW_SECTION_H (nn).sh_link);
- /* For symbol tables, info is a symbol table index,
- so don't change it. */
- if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB
- && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM)
- PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
-
- if (old_sbss_index != -1)
- if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".sbss"))
- {
- NEW_SECTION_H (nn).sh_offset =
- round_up (NEW_SECTION_H (nn).sh_offset,
- NEW_SECTION_H (nn).sh_addralign);
- NEW_SECTION_H (nn).sh_type = SHT_PROGBITS;
- }
+ /* Any section that was originally placed after the .bss
+ section should now be offset by NEW_DATA2_SIZE. */
+ if (new_shdr->sh_offset >= old_bss_offset)
+ new_shdr->sh_offset += new_data2_size;
/* Now, start to copy the content of sections. */
- if (NEW_SECTION_H (nn).sh_type == SHT_NULL
- || NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
+ if (new_shdr->sh_type == SHT_NULL
+ || new_shdr->sh_type == SHT_NOBITS)
continue;
- /* Write out the sections. .data and .data1 (and data2, called
- ".data" in the strings table) get copied from the current process
- instead of the old file. */
- if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".sdata")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".lit4")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".lit8")
+ /* Some sections are copied from the current process instead of
+ the old file. */
+ if (!strcmp (old_section_names + new_shdr->sh_name, ".data")
+ || !strcmp (old_section_names + new_shdr->sh_name, ".sdata")
+ || !strcmp (old_section_names + new_shdr->sh_name, ".lit4")
+ || !strcmp (old_section_names + new_shdr->sh_name, ".lit8")
/* The conditional bit below was in Oliva's original code
(1999-08-25) and seems to have been dropped by mistake
subsequently. It prevents a crash at startup under X in
loader, but I never got anywhere with an SGI support call
seeking clues. -- fx 2002-11-29. */
#ifdef IRIX6_5
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".got")
+ || !strcmp (old_section_names + new_shdr->sh_name, ".got")
#endif
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".sdata1")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".data1")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".sbss"))
- src = (caddr_t) OLD_SECTION_H (n).sh_addr;
+ || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1")
+ || !strcmp (old_section_names + new_shdr->sh_name, ".data1"))
+ src = (caddr_t) old_shdr->sh_addr;
else
- src = old_base + OLD_SECTION_H (n).sh_offset;
-
- memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
- NEW_SECTION_H (nn).sh_size);
+ src = old_base + old_shdr->sh_offset;
-#if defined __alpha__ && !defined __OpenBSD__
- /* Update Alpha COFF symbol table: */
- if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug")
- == 0)
- {
- pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base);
-
- symhdr->cbLineOffset += new_data2_size;
- symhdr->cbDnOffset += new_data2_size;
- symhdr->cbPdOffset += new_data2_size;
- symhdr->cbSymOffset += new_data2_size;
- symhdr->cbOptOffset += new_data2_size;
- symhdr->cbAuxOffset += new_data2_size;
- symhdr->cbSsOffset += new_data2_size;
- symhdr->cbSsExtOffset += new_data2_size;
- symhdr->cbFdOffset += new_data2_size;
- symhdr->cbRfdOffset += new_data2_size;
- symhdr->cbExtOffset += new_data2_size;
- }
-#endif /* __alpha__ && !__OpenBSD__ */
+ memcpy (new_shdr->sh_offset + new_base, src, new_shdr->sh_size);
-#if defined (_SYSTYPE_SYSV)
- if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG
- && old_mdebug_index != -1)
+#if (defined __alpha__ && !defined __OpenBSD__) || defined _SYSTYPE_SYSV
+ /* Update Alpha and MIPS COFF debug symbol table. */
+ if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
+ && new_shdr->sh_offset - old_shdr->sh_offset != 0
+#if defined _SYSTYPE_SYSV
+ && new_shdr->sh_type == SHT_MIPS_DEBUG
+#endif
+ )
{
- ptrdiff_t new_offset = NEW_SECTION_H (nn).sh_offset;
- ptrdiff_t old_offset = OLD_SECTION_H (old_mdebug_index).sh_offset;
- ptrdiff_t diff = new_offset - old_offset;
- HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base);
-
- if (diff)
- {
- phdr->cbLineOffset += diff;
- phdr->cbDnOffset += diff;
- phdr->cbPdOffset += diff;
- phdr->cbSymOffset += diff;
- phdr->cbOptOffset += diff;
- phdr->cbAuxOffset += diff;
- phdr->cbSsOffset += diff;
- phdr->cbSsExtOffset += diff;
- phdr->cbFdOffset += diff;
- phdr->cbRfdOffset += diff;
- phdr->cbExtOffset += diff;
- }
+ ptrdiff_t diff = new_shdr->sh_offset - old_shdr->sh_offset;
+ HDRR *phdr = (HDRR *) (new_shdr->sh_offset + new_base);
+
+ phdr->cbLineOffset += diff;
+ phdr->cbDnOffset += diff;
+ phdr->cbPdOffset += diff;
+ phdr->cbSymOffset += diff;
+ phdr->cbOptOffset += diff;
+ phdr->cbAuxOffset += diff;
+ phdr->cbSsOffset += diff;
+ phdr->cbSsExtOffset += diff;
+ phdr->cbFdOffset += diff;
+ phdr->cbRfdOffset += diff;
+ phdr->cbExtOffset += diff;
}
-#endif /* _SYSTYPE_SYSV */
+#endif /* __alpha__ || _SYSTYPE_SYSV */
#if __sgi
/* Adjust the HDRR offsets in .mdebug and copy the
the ld bug that gets the line table in a hole in the
elf file rather than in the .mdebug section proper.
David Anderson. davea@sgi.com Jan 16,1994. */
- if (n == old_mdebug_index)
+ if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
+ && new_shdr->sh_offset - old_shdr->sh_offset != 0)
{
#define MDEBUGADJUST(__ct,__fileaddr) \
if (n_phdrr->__ct > 0) \
n_phdrr->__fileaddr += movement; \
}
- HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
- HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
- unsigned movement = new_data2_size;
+ HDRR *o_phdrr = (HDRR *) ((byte *) old_base + old_shdr->sh_offset);
+ HDRR *n_phdrr = (HDRR *) ((byte *) new_base + new_shdr->sh_offset);
+ ptrdiff_t movement = new_shdr->sh_offset - old_shdr->sh_offset;
MDEBUGADJUST (idnMax, cbDnOffset);
MDEBUGADJUST (ipdMax, cbPdOffset);
requires special handling. */
if (n_phdrr->cbLine > 0)
{
- if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
- + OLD_SECTION_H (n).sh_size))
- {
- /* line data is in a hole in elf. do special copy and adjust
- for this ld mistake.
- */
- n_phdrr->cbLineOffset += movement;
+ n_phdrr->cbLineOffset += movement;
- memcpy (n_phdrr->cbLineOffset + new_base,
- o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
- }
- else
- {
- /* somehow line data is in .mdebug as it is supposed to be. */
- MDEBUGADJUST (cbLine, cbLineOffset);
- }
+ if (o_phdrr->cbLineOffset > (old_shdr->sh_offset
+ + old_shdr->sh_size))
+ /* If not covered by section, it hasn't yet been copied. */
+ memcpy (n_phdrr->cbLineOffset + new_base,
+ o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
}
}
#endif /* __sgi */
-
- /* If it is the symbol table, its st_shndx field needs to be patched. */
- if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
- || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
- {
- ElfW (Shdr) *spt = &NEW_SECTION_H (nn);
- ptrdiff_t num = spt->sh_size / spt->sh_entsize;
- ElfW (Sym) * sym = (ElfW (Sym) *) (NEW_SECTION_H (nn).sh_offset +
- new_base);
- for (; num--; sym++)
- {
- if ((sym->st_shndx == SHN_UNDEF)
- || (sym->st_shndx == SHN_ABS)
- || (sym->st_shndx == SHN_COMMON))
- continue;
-
- PATCH_INDEX (sym->st_shndx);
- }
- }
}
/* Update the symbol values of _edata and _end. */
{
byte *symnames;
ElfW (Sym) *symp, *symendp;
+ ElfW (Shdr) *sym_shdr = &NEW_SECTION_H (n);
- if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM
- && NEW_SECTION_H (n).sh_type != SHT_SYMTAB)
+ if (sym_shdr->sh_type != SHT_DYNSYM
+ && sym_shdr->sh_type != SHT_SYMTAB)
continue;
symnames = ((byte *) new_base
- + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset);
- symp = (ElfW (Sym) *) (NEW_SECTION_H (n).sh_offset + new_base);
- symendp = (ElfW (Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
+ + NEW_SECTION_H (sym_shdr->sh_link).sh_offset);
+ symp = (ElfW (Sym) *) (sym_shdr->sh_offset + new_base);
+ symendp = (ElfW (Sym) *) ((byte *) symp + sym_shdr->sh_size);
for (; symp < symendp; symp ++)
{
if (strncmp ((char *) (symnames + symp->st_name),
"_OBJC_", sizeof ("_OBJC_") - 1) == 0)
{
- caddr_t old, new;
-
- new = ((symp->st_value - NEW_SECTION_H (symp->st_shndx).sh_addr)
- + NEW_SECTION_H (symp->st_shndx).sh_offset + new_base);
- /* "Unpatch" index. */
- nn = symp->st_shndx;
- if (nn > old_bss_index)
- nn--;
- if (nn == old_bss_index)
- memset (new, 0, symp->st_size);
- else
+ ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx);
+ if (new_shdr->sh_type != SHT_NOBITS)
{
- old = ((symp->st_value
- - NEW_SECTION_H (symp->st_shndx).sh_addr)
- + OLD_SECTION_H (nn).sh_offset + old_base);
- memcpy (new, old, symp->st_size);
+ ElfW (Shdr) *old_shdr = &OLD_SECTION_H (symp->st_shndx);
+ ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
+ ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
+
+ if (old_shdr->sh_type == SHT_NOBITS)
+ memset (new_base + newoff, 0, symp->st_size);
+ else
+ {
+ ptrdiff_t oldoff = reladdr + old_shdr->sh_offset;
+ memcpy (new_base + newoff, old_base + oldoff,
+ symp->st_size);
+ }
}
}
#endif
}
}
- /* This loop seeks out relocation sections for the data section, so
- that it can undo relocations performed by the runtime linker. */
+ /* Modify the names of sections we changed from SHT_NOBITS to
+ SHT_PROGBITS. This is really just cosmetic, but some tools that
+ (wrongly) operate on section names rather than types might be
+ confused by a SHT_PROGBITS .bss section. */
+ new_section_names = ((char *) new_base
+ + NEW_SECTION_H (new_file_h->e_shstrndx).sh_offset);
for (n = new_file_h->e_shnum; 0 < --n; )
{
- ElfW (Shdr) section = NEW_SECTION_H (n);
+ ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
+ ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
+
+ /* Replace the leading '.' with ','. When .shstrtab is string
+ merged this will rename both .bss and .rela.bss to ,bss and
+ .rela,bss. */
+ if (old_shdr->sh_type == SHT_NOBITS
+ && new_shdr->sh_type == SHT_PROGBITS)
+ *(new_section_names + new_shdr->sh_name) = ',';
+ }
- /* Cause a compilation error if anyone uses n instead of nn below. */
- #define n ((void) 0);
- n /* Prevent 'macro "n" is not used' warnings. */
+ /* This loop seeks out relocation sections for the data section, so
+ that it can undo relocations performed by the runtime loader. */
+ for (n = new_file_h->e_shnum; 0 < --n; )
+ {
+ ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n);
+ ElfW (Shdr) *shdr;
- switch (section.sh_type)
+ switch (rel_shdr->sh_type)
{
default:
break;
/* This code handles two different size structs, but there should
be no harm in that provided that r_offset is always the first
member. */
- nn = section.sh_info;
- if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".sdata")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".lit4")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".lit8")
+ shdr = &NEW_SECTION_H (rel_shdr->sh_info);
+ if (!strcmp (old_section_names + shdr->sh_name, ".data")
+ || !strcmp (old_section_names + shdr->sh_name, ".sdata")
+ || !strcmp (old_section_names + shdr->sh_name, ".lit4")
+ || !strcmp (old_section_names + shdr->sh_name, ".lit8")
#ifdef IRIX6_5 /* see above */
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".got")
+ || !strcmp (old_section_names + shdr->sh_name, ".got")
#endif
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".sdata1")
- || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
- ".data1"))
+ || !strcmp (old_section_names + shdr->sh_name, ".sdata1")
+ || !strcmp (old_section_names + shdr->sh_name, ".data1"))
{
- ElfW (Addr) offset = (NEW_SECTION_H (nn).sh_addr
- - NEW_SECTION_H (nn).sh_offset);
- caddr_t reloc = old_base + section.sh_offset, end;
- for (end = reloc + section.sh_size; reloc < end;
- reloc += section.sh_entsize)
+ ElfW (Addr) offset = shdr->sh_addr - shdr->sh_offset;
+ caddr_t reloc = old_base + rel_shdr->sh_offset, end;
+ for (end = reloc + rel_shdr->sh_size;
+ reloc < end;
+ reloc += rel_shdr->sh_entsize)
{
ElfW (Addr) addr = ((ElfW (Rel) *) reloc)->r_offset - offset;
-#ifdef __alpha__
- /* The Alpha ELF binutils currently have a bug that
- sometimes results in relocs that contain all
- zeroes. Work around this for now... */
+ /* Ignore R_*_NONE relocs. */
if (((ElfW (Rel) *) reloc)->r_offset == 0)
continue;
-#endif
- memcpy (new_base + addr, old_base + addr, sizeof (ElfW (Addr)));
+ /* Assume reloc applies to a word.
+ ??? This is not always true, eg. TLS module/index
+ pair in .got which occupies two words. */
+ memcpy (new_base + addr, old_base + addr,
+ sizeof (ElfW (Addr)));
}
}
break;
}
-
- #undef n
}
/* Write out new_file, and free the buffers. */
extern void fset_redisplay (struct frame *f);
extern void bset_redisplay (struct buffer *b);
extern void bset_update_mode_line (struct buffer *b);
+extern void maybe_set_redisplay (Lisp_Object);
/* Call this to tell redisplay to look for other windows than selected-window
that need to be redisplayed. Calling one of the *set_redisplay functions
above already does it, so it's only needed in unusual cases. */
b->text->redisplay = true;
}
+void
+maybe_set_redisplay (Lisp_Object symbol)
+{
+ if (HASH_TABLE_P (Vredisplay__variables)
+ && hash_lookup (XHASH_TABLE (Vredisplay__variables), symbol, NULL) >= 0)
+ {
+ bset_update_mode_line (current_buffer);
+ current_buffer->prevent_redisplay_optimizations_p = true;
+ }
+}
+
#ifdef GLYPH_DEBUG
/* True means print traces of redisplay if compiled with
{
struct frame *f = XFRAME (frame);
- if (FRAME_WINDOW_P (f)
- || FRAME_MINIBUF_ONLY_P (f)
- || f->explicit_name)
+ if ((FRAME_WINDOW_P (f)
+ || FRAME_MINIBUF_ONLY_P (f)
+ || f->explicit_name)
+ && NILP (Fframe_parameter (frame, Qtooltip)))
{
/* Do we have more than one visible frame on this X display? */
Lisp_Object tail, other_frame, fmt;
DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
doc: /* */);
Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
+
+ DEFVAR_LISP ("redisplay--variables", Vredisplay__variables,
+ doc: /* A hash-table of variables changing which triggers a thorough redisplay. */);
+ Vredisplay__variables = Qnil;
}
/* Do we have room for this component followed by a '\0'? */
if (path_size - path_len <= next_len)
- {
- if (min (PTRDIFF_MAX, SIZE_MAX) / 2 - 1 - path_len < next_len)
- memory_full (SIZE_MAX);
- path_size = (path_len + next_len + 1) * 2;
- path = xrealloc (path, path_size);
- }
+ path = xpalloc (path, &path_size, path_len - path_size + next_len + 1,
+ -1, sizeof *path);
memcpy (path + path_len, next, next_len);
path_len += next_len;
Atom type, int format, unsigned long size)
{
ptrdiff_t format_bytes = format >> 3;
- if (PTRDIFF_MAX / format_bytes < size)
+ ptrdiff_t data_bytes;
+ if (INT_MULTIPLY_WRAPV (size, format_bytes, &data_bytes))
memory_full (SIZE_MAX);
return selection_data_to_lisp_data (FRAME_DISPLAY_INFO (f), data,
- size * format_bytes, type, format);
+ data_bytes, type, format);
}
DEFUN ("x-get-atom-name", Fx_get_atom_name,
props[props_idx]->name = xstrdup (SmRestartCommand);
props[props_idx]->type = xstrdup (SmLISTofARRAY8);
/* /path/to/emacs, --smid=xxx --no-splash --chdir=dir ... */
- if (INT_MAX - 3 < initial_argc)
+ if (INT_ADD_WRAPV (initial_argc, 3, &i))
memory_full (SIZE_MAX);
- i = 3 + initial_argc;
props[props_idx]->num_vals = i;
vp = xnmalloc (i, sizeof *vp);
props[props_idx]->vals = vp;
struct terminal *terminal;
struct x_display_info *dpyinfo;
XrmDatabase xrdb;
- ptrdiff_t lim;
block_input ();
dpyinfo->display = dpy;
dpyinfo->connection = ConnectionNumber (dpyinfo->display);
+ /* http://lists.gnu.org/archive/html/emacs-devel/2015-11/msg00194.html */
+ dpyinfo->smallest_font_height = 1;
+ dpyinfo->smallest_char_width = 1;
+
/* Set the name of the terminal. */
terminal->name = xlispstrdup (display_name);
XSetAfterFunction (x_current_display, x_trace_wire);
#endif
- lim = min (PTRDIFF_MAX, SIZE_MAX) - sizeof "@";
Lisp_Object system_name = Fsystem_name ();
- if (lim - SBYTES (Vinvocation_name) < SBYTES (system_name))
+ ptrdiff_t nbytes;
+ if (INT_ADD_WRAPV (SBYTES (Vinvocation_name), SBYTES (system_name) + 2,
+ &nbytes))
memory_full (SIZE_MAX);
dpyinfo->x_id = ++x_display_id;
- dpyinfo->x_id_name = xmalloc (SBYTES (Vinvocation_name)
- + SBYTES (system_name) + 2);
+ dpyinfo->x_id_name = xmalloc (nbytes);
char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name);
*nametail++ = '@';
lispstpcpy (nametail, system_name);
--- /dev/null
+;;; abbrev-tests.el --- Test suite for abbrevs.
+
+;; Copyright (C) 2015 Free Software Foundation, Inc.
+
+;; Author: Eli Zaretskii <eliz@gnu.org>
+;; Keywords: abbrevs
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'abbrev)
+
+(ert-deftest copy-abbrev-table-test ()
+ (defvar foo-abbrev-table nil) ; Avoid compiler warning
+ (define-abbrev-table 'foo-abbrev-table
+ '())
+ (should (abbrev-table-p foo-abbrev-table))
+ ;; Bug 21828
+ (let ((new-foo-abbrev-table
+ (condition-case nil
+ (copy-abbrev-table foo-abbrev-table)
+ (error nil))))
+ (should (abbrev-table-p new-foo-abbrev-table)))
+ (should-not (string-equal (buffer-name) "*Backtrace*")))
+
+(provide 'abbrev-tests)
+
+;;; abbrev-tests.el ends here
(kill-buffer buf))
(ignore-errors (delete-file tmpfile)))))
-(ert-deftest auto-revert-test01-auto-revert-tail-mode ()
+;; This is inspired by Bug#21841.
+(ert-deftest auto-revert-test01-auto-revert-several-files ()
+ "Check autorevert for several files at once."
+ (skip-unless (executable-find "cp"))
+
+ (let* ((cp (executable-find "cp"))
+ (tmpdir1 (make-temp-file "auto-revert-test" 'dir))
+ (tmpdir2 (make-temp-file "auto-revert-test" 'dir))
+ (tmpfile1
+ (make-temp-file (expand-file-name "auto-revert-test" tmpdir1)))
+ (tmpfile2
+ (make-temp-file (expand-file-name "auto-revert-test" tmpdir1)))
+ buf1 buf2)
+ (unwind-protect
+ (progn
+ (with-current-buffer (get-buffer-create "*Messages*")
+ (narrow-to-region (point-max) (point-max)))
+ (write-region "any text" nil tmpfile1 nil 'no-message)
+ (setq buf1 (find-file-noselect tmpfile1))
+ (write-region "any text" nil tmpfile2 nil 'no-message)
+ (setq buf2 (find-file-noselect tmpfile2))
+
+ (dolist (buf (list buf1 buf2))
+ (with-current-buffer buf
+ (should (string-equal (buffer-string) "any text"))
+ ;; `buffer-stale--default-function' checks for
+ ;; `verify-visited-file-modtime'. We must ensure that
+ ;; it returns nil.
+ (sleep-for 1)
+ (auto-revert-mode 1)
+ (should auto-revert-mode)))
+
+ ;; Modify files. We wait for a second, in order to have
+ ;; another timestamp.
+ (sleep-for 1)
+ (write-region
+ "another text" nil
+ (expand-file-name (file-name-nondirectory tmpfile1) tmpdir2)
+ nil 'no-message)
+ (write-region
+ "another text" nil
+ (expand-file-name (file-name-nondirectory tmpfile2) tmpdir2)
+ nil 'no-message)
+ ;;(copy-directory tmpdir2 tmpdir1 nil 'copy-contents)
+ ;; Strange, that `copy-directory' does not work as expected.
+ ;; The following shell command is not portable on all
+ ;; platforms, unfortunately.
+ (shell-command (format "%s -f %s/* %s" cp tmpdir2 tmpdir1))
+
+ ;; Check, that the buffers have been reverted.
+ (dolist (buf (list buf1 buf2))
+ (with-current-buffer buf
+ (auto-revert--wait-for-revert buf)
+ (should (string-match "another text" (buffer-string))))))
+
+ ;; Exit.
+ (with-current-buffer "*Messages*" (widen))
+ (ignore-errors
+ (dolist (buf (list buf1 buf2))
+ (with-current-buffer buf (set-buffer-modified-p nil))
+ (kill-buffer buf)))
+ (ignore-errors (delete-directory tmpdir1 'recursive))
+ (ignore-errors (delete-directory tmpdir2 'recursive)))))
+
+(ert-deftest auto-revert-test02-auto-revert-tail-mode ()
"Check autorevert tail mode."
;; `auto-revert-buffers' runs every 5". And we must wait, until the
;; file has been reverted.
(ignore-errors (kill-buffer buf))
(ignore-errors (delete-file tmpfile)))))
-(ert-deftest auto-revert-test02-auto-revert-mode-dired ()
+(ert-deftest auto-revert-test03-auto-revert-mode-dired ()
"Check autorevert for dired."
;; `auto-revert-buffers' runs every 5". And we must wait, until the
;; file has been reverted.
--- /dev/null
+;;; buffer-tests.el --- tests for buffer.c functions -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest overlay-modification-hooks-message-other-buf ()
+ "Test for bug#21824.
+After a modification-hook has been run and there is an overlay in
+the *Messages* buffer, the message coalescing [2 times] wrongly
+runs the modification-hook of the overlay in the 1st buffer, but
+with parameters from the *Messages* buffer modification."
+ (let ((buf nil)
+ (msg-ov nil))
+ (with-temp-buffer
+ (insert "123")
+ (overlay-put (make-overlay 1 3)
+ 'modification-hooks
+ (list (lambda (&rest _)
+ (setq buf (current-buffer)))))
+ (goto-char 2)
+ (insert "x")
+ (unwind-protect
+ (progn
+ (setq msg-ov (make-overlay 1 1 (get-buffer-create "*Messages*")))
+ (message "a message")
+ (message "a message")
+ (should (eq buf (current-buffer))))
+ (when msg-ov (delete-overlay msg-ov))))))
+
+;;; buffer-tests.el ends here
(cl-defstruct (mystruct
(:constructor cl-lib--con-1 (&aux (abc 1)))
- (:constructor cl-lib--con-2 (&optional def)))
+ (:constructor cl-lib--con-2 (&optional def) "Constructor docstring."))
+ "General docstring."
(abc 5 :readonly t) (def nil))
(ert-deftest cl-lib-struct-accessors ()
(let ((x (make-mystruct :abc 1 :def 2)))
(`((cl-tag-slot) (abc 5 :readonly t)
(def . ,(or `nil `(nil))))
t)))))
+(ert-deftest cl-lib-struct-constructors ()
+ (should (equal (documentation 'cl-lib--con-2 t)
+ "Constructor docstring."))
+ (should (mystruct-p (cl-lib--con-1)))
+ (should (mystruct-p (cl-lib--con-2))))
(ert-deftest cl-lib-arglist-performance ()
;; An `&aux' should not cause lambda's arglist to be turned into an &rest
(while (null ,until)
(read-event nil nil 0.1))))
-(defmacro file-notify--test-with-events (timeout events &rest body)
+(defmacro file-notify--test-with-events (events &rest body)
"Run BODY collecting events and then compare with EVENTS.
-Don't wait longer than TIMEOUT seconds for the events to be delivered."
- (declare (indent 2))
+Don't wait longer than timeout seconds for the events to be delivered."
+ (declare (indent 1))
(let ((outer (make-symbol "outer")))
`(let ((,outer file-notify--test-events))
(setq file-notify--test-expected-events
(let (file-notify--test-events)
,@body
(file-notify--wait-for-events
- ,timeout (= (length ,events) (length file-notify--test-events)))
+ (file-notify--test-timeout)
+ (= (length ,events) (length file-notify--test-events)))
(should (equal ,events (mapcar #'cadr file-notify--test-events)))
(setq ,outer (append ,outer file-notify--test-events)))
(setq file-notify--test-events ,outer))))
(ert-deftest file-notify-test02-events ()
"Check file creation/change/removal notifications."
(skip-unless (file-notify--test-local-enabled))
+ ;; Under cygwin there are so bad timings that it doesn't make sense to test.
+ (skip-unless (not (eq system-type 'cygwin)))
(setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
file-notify--test-tmpfile1 (file-notify--test-make-temp-name))
(file-notify-add-watch
file-notify--test-tmpfile
'(change) 'file-notify--test-event-handler))
- (file-notify--test-with-events
- (file-notify--test-timeout) '(created changed deleted)
+ (file-notify--test-with-events '(created changed deleted)
(write-region
"any text" nil file-notify--test-tmpfile nil 'no-message)
(delete-file file-notify--test-tmpfile))
file-notify--test-tmpfile
'(change) 'file-notify--test-event-handler))
(file-notify--test-with-events
- (file-notify--test-timeout)
;; There are two `deleted' events, for the file and for
;; the directory.
'(created changed deleted deleted stopped)
'(change) 'file-notify--test-event-handler))
(should file-notify--test-desc)
(file-notify--test-with-events
- (file-notify--test-timeout)
;; w32notify does not distinguish between `changed' and
;; `attribute-changed'.
(if (eq file-notify--library 'w32notify)
file-notify--test-tmpfile
'(change) 'file-notify--test-event-handler))
(should file-notify--test-desc)
- (file-notify--test-with-events
- (file-notify--test-timeout) '(created changed renamed)
+ (file-notify--test-with-events '(created changed renamed)
(write-region
"any text" nil file-notify--test-tmpfile nil 'no-message)
(rename-file file-notify--test-tmpfile file-notify--test-tmpfile1)
file-notify--test-tmpfile
'(attribute-change) 'file-notify--test-event-handler))
(file-notify--test-with-events
- (file-notify--test-timeout)
(if (file-remote-p temporary-file-directory)
;; In the remote case, `write-region' raises also an
;; `attribute-changed' event.
(ert-deftest file-notify-test04-file-validity ()
"Check `file-notify-valid-p' for files."
(skip-unless (file-notify--test-local-enabled))
+ ;; Under cygwin there are so bad timings that it doesn't make sense to test.
+ (skip-unless (not (eq system-type 'cygwin)))
(unwind-protect
(progn
(file-notify-add-watch
file-notify--test-tmpfile
'(change) #'file-notify--test-event-handler))
- (file-notify--test-with-events
- (file-notify--test-timeout) '(created changed deleted)
+ (file-notify--test-with-events '(created changed deleted)
(should (file-notify-valid-p file-notify--test-desc))
(write-region
"any text" nil file-notify--test-tmpfile nil 'no-message)
(file-notify-add-watch
file-notify--test-tmpfile
'(change) #'file-notify--test-event-handler))
- (file-notify--test-with-events
- (file-notify--test-timeout) '(created changed deleted stopped)
+ (file-notify--test-with-events '(created changed deleted stopped)
(should (file-notify-valid-p file-notify--test-desc))
(write-region
"any text" nil file-notify--test-tmpfile nil 'no-message)
;; TODO:
;; * For w32notify, no stopped events arrive when a directory is removed.
+;; * Try to handle arriving events under cygwin reliably.
(provide 'file-notify-tests)
;;; file-notify-tests.el ends here
(should (equal (json-read-from-string "\"\\nasd\\u0444\\u044b\\u0432fgh\\t\"")
"\nasdфывfgh\t")))
+(ert-deftest test-json-path-to-position-with-objects ()
+ (let* ((json-string "{\"foo\": {\"bar\": {\"baz\": \"value\"}}}")
+ (matched-path (json-path-to-position 32 json-string)))
+ (should (equal (plist-get matched-path :path) '("foo" "bar" "baz")))
+ (should (equal (plist-get matched-path :match-start) 25))
+ (should (equal (plist-get matched-path :match-end) 32))))
+
+(ert-deftest test-json-path-to-position-with-arrays ()
+ (let* ((json-string "{\"foo\": [\"bar\", [\"baz\"]]}")
+ (matched-path (json-path-to-position 20 json-string)))
+ (should (equal (plist-get matched-path :path) '("foo" 1 0)))
+ (should (equal (plist-get matched-path :match-start) 18))
+ (should (equal (plist-get matched-path :match-end) 23))))
+
+(ert-deftest test-json-path-to-position-no-match ()
+ (let* ((json-string "{\"foo\": {\"bar\": \"baz\"}}")
+ (matched-path (json-path-to-position 5 json-string)))
+ (should (null matched-path))))
+
(provide 'json-tests)
;;; json-tests.el ends here
(should (equal (when t 'x 2) 2))
(should (equal (when nil 'x 1) nil))
(should (equal (when nil 'x 2) nil))
- (should (equal (macroexpand-all '(when a b))
- '(if a b)))
+ (let ((x 1))
+ (should-not (when nil
+ (setq x (1+ x))
+ x))
+ (should (= x 1))
+ (should (= 2 (when t
+ (setq x (1+ x))
+ x)))
+ (should (= x 2)))
(should (equal (macroexpand-all '(when a b c d))
'(if a (progn b c d)))))