diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.in | 4 | ||||
-rw-r--r-- | src/bidi.c | 14 | ||||
-rw-r--r-- | src/buffer.h | 9 | ||||
-rw-r--r-- | src/conf_post.h | 5 | ||||
-rw-r--r-- | src/editfns.c | 203 | ||||
-rw-r--r-- | src/emacs-module.c | 7 | ||||
-rw-r--r-- | src/emacs-module.h.in | 106 | ||||
-rw-r--r-- | src/emacs.c | 6 | ||||
-rw-r--r-- | src/fileio.c | 6 | ||||
-rw-r--r-- | src/gmalloc.c | 83 | ||||
-rw-r--r-- | src/image.c | 10 | ||||
-rw-r--r-- | src/lread.c | 11 | ||||
-rw-r--r-- | src/module-env-25.h (renamed from src/emacs-module.h) | 107 | ||||
-rw-r--r-- | src/module-env-26.h | 3 | ||||
-rw-r--r-- | src/unexelf.c | 12 | ||||
-rw-r--r-- | src/widget.c | 13 | ||||
-rw-r--r-- | src/widget.h | 2 | ||||
-rw-r--r-- | src/xfns.c | 2 |
18 files changed, 430 insertions, 173 deletions
diff --git a/src/Makefile.in b/src/Makefile.in index 2be24ac192a..57969d5fc58 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -639,13 +639,13 @@ mostlyclean: rm -f globals.h gl-stamp rm -f *.res *.tmp clean: mostlyclean - rm -f emacs-*.*.*$(EXEEXT) emacs$(EXEEXT) $(DEPDIR)/* + rm -f emacs-*.*.*[0-9]$(EXEEXT) emacs$(EXEEXT) $(DEPDIR)/* ## bootstrap-clean is used to clean up just before a bootstrap. ## It should remove all files generated during a compilation/bootstrap, ## but not things like config.status or TAGS. bootstrap-clean: clean - rm -f epaths.h config.h config.stamp + rm -f emacs-module.h epaths.h config.h config.stamp if test -f ./.gdbinit; then \ mv ./.gdbinit ./.gdbinit.save; \ if test -f "$(srcdir)/.gdbinit"; then rm -f ./.gdbinit.save; \ diff --git a/src/bidi.c b/src/bidi.c index dce0bf695f6..e34da778ba0 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -565,9 +565,7 @@ bidi_copy_it (struct bidi_it *to, struct bidi_it *from) RTL characters in the offending line of text. */ /* Do we need to allow customization of this limit? */ #define BIDI_CACHE_MAX_ELTS_PER_SLOT 50000 -#if BIDI_CACHE_CHUNK >= BIDI_CACHE_MAX_ELTS_PER_SLOT -# error BIDI_CACHE_CHUNK must be less than BIDI_CACHE_MAX_ELTS_PER_SLOT -#endif +verify (BIDI_CACHE_CHUNK < BIDI_CACHE_MAX_ELTS_PER_SLOT); static ptrdiff_t bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT; static struct bidi_it *bidi_cache; static ptrdiff_t bidi_cache_size = 0; @@ -2468,9 +2466,11 @@ typedef struct bpa_stack_entry { unsigned flags : 2; } bpa_stack_entry; -/* With MAX_ALLOCA of 16KB, this should allow at least 1K slots in the +/* Allow for the two struct bidi_it objects too, since they can be big. + With MAX_ALLOCA of 16 KiB, this should allow at least 900 slots in the BPA stack, which should be more than enough for actual bidi text. */ -#define MAX_BPA_STACK ((int)max (MAX_ALLOCA / sizeof (bpa_stack_entry), 1)) +enum { MAX_BPA_STACK = max (1, ((MAX_ALLOCA - 2 * sizeof (struct bidi_it)) + / sizeof (bpa_stack_entry))) }; /* UAX#9 says to match opening brackets with the matching closing brackets or their canonical equivalents. As of Unicode 8.0, there @@ -2517,7 +2517,7 @@ typedef struct bpa_stack_entry { #define PUSH_BPA_STACK \ do { \ int ch; \ - if (bpa_sp < MAX_BPA_STACK - 1) \ + if (bpa_sp < MAX_BPA_STACK - 1 && bidi_cache_last_idx <= INT_MAX) \ { \ bpa_sp++; \ ch = CANONICAL_EQU (bidi_it->ch); \ @@ -2563,7 +2563,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) ptrdiff_t pairing_pos; int idx_at_entry = bidi_cache_idx; - eassert (MAX_BPA_STACK >= 100); + verify (MAX_BPA_STACK >= 100); bidi_copy_it (&saved_it, bidi_it); /* bidi_cache_iterator_state refuses to cache on backward scans, and bidi_cache_fetch_state doesn't bring scan_dir from the diff --git a/src/buffer.h b/src/buffer.h index a2bdc4e7294..be270fe4823 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -412,6 +412,15 @@ extern void enlarge_buffer_text (struct buffer *, ptrdiff_t); ? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \ : BUF_FETCH_BYTE ((buf), (pos))) +/* Return character at byte position POS in buffer BUF. If BUF is + unibyte and the character is not ASCII, make the returning + character multibyte. */ + +#define BUF_FETCH_CHAR_AS_MULTIBYTE(buf, pos) \ + (! NILP (BVAR ((buf), enable_multibyte_characters)) \ + ? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \ + : UNIBYTE_TO_CHAR (BUF_FETCH_BYTE ((buf), (pos)))) + /* Return the byte at byte position N in buffer BUF. */ #define BUF_FETCH_BYTE(buf, n) \ diff --git a/src/conf_post.h b/src/conf_post.h index 18b096e2cf6..e1d6a9397d3 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -57,10 +57,13 @@ typedef bool bool_bf; #endif /* Simulate __has_attribute on compilers that lack it. It is used only - on arguments like alloc_size that are handled in this simulation. */ + on arguments like alloc_size that are handled in this simulation. + __has_attribute should be used only in #if expressions, as Oracle + Studio 12.5's __has_attribute does not work in plain code. */ #ifndef __has_attribute # define __has_attribute(a) __has_attribute_##a # define __has_attribute_alloc_size GNUC_PREREQ (4, 3, 0) +# define __has_attribute_cleanup GNUC_PREREQ (3, 4, 0) # define __has_attribute_externally_visible GNUC_PREREQ (4, 1, 0) # define __has_attribute_no_address_safety_analysis false # define __has_attribute_no_sanitize_address GNUC_PREREQ (4, 8, 0) diff --git a/src/editfns.c b/src/editfns.c index 43b17f9f116..da99c055b54 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -3105,6 +3105,207 @@ determines whether case is significant or ignored. */) /* Same length too => they are equal. */ return make_number (0); } + + +/* Set up necessary definitions for diffseq.h; see comments in + diffseq.h for explanation. */ + +#undef ELEMENT +#undef EQUAL + +#define XVECREF_YVECREF_EQUAL(ctx, xoff, yoff) \ + buffer_chars_equal ((ctx), (xoff), (yoff)) + +#define OFFSET ptrdiff_t + +#define EXTRA_CONTEXT_FIELDS \ + /* Buffers to compare. */ \ + struct buffer *buffer_a; \ + struct buffer *buffer_b; \ + /* Bit vectors recording for each character whether it was deleted + or inserted. */ \ + unsigned char *deletions; \ + unsigned char *insertions; + +#define NOTE_DELETE(ctx, xoff) set_bit ((ctx)->deletions, (xoff)) +#define NOTE_INSERT(ctx, yoff) set_bit ((ctx)->insertions, (yoff)) + +struct context; +static void set_bit (unsigned char *, OFFSET); +static bool bit_is_set (const unsigned char *, OFFSET); +static bool buffer_chars_equal (struct context *, OFFSET, OFFSET); + +#include "minmax.h" +#include "diffseq.h" + +DEFUN ("replace-buffer-contents", Freplace_buffer_contents, + Sreplace_buffer_contents, 1, 1, "bSource buffer: ", + doc: /* Replace accessible portion of current buffer with that of SOURCE. +SOURCE can be a buffer or a string that names a buffer. +Interactively, prompt for SOURCE. +As far as possible the replacement is non-destructive, i.e. existing +buffer contents, markers, properties, and overlays in the current +buffer stay intact. */) + (Lisp_Object source) +{ + struct buffer *a = current_buffer; + Lisp_Object source_buffer = Fget_buffer (source); + if (NILP (source_buffer)) + nsberror (source); + struct buffer *b = XBUFFER (source_buffer); + if (! BUFFER_LIVE_P (b)) + error ("Selecting deleted buffer"); + if (a == b) + error ("Cannot replace a buffer with itself"); + + ptrdiff_t min_a = BEGV; + ptrdiff_t min_b = BUF_BEGV (b); + ptrdiff_t size_a = ZV - min_a; + ptrdiff_t size_b = BUF_ZV (b) - min_b; + eassume (size_a >= 0); + eassume (size_b >= 0); + bool a_empty = size_a == 0; + bool b_empty = size_b == 0; + + /* Handle trivial cases where at least one accessible portion is + empty. */ + + if (a_empty && b_empty) + return Qnil; + + if (a_empty) + return Finsert_buffer_substring (source, Qnil, Qnil); + + if (b_empty) + { + del_range_both (BEGV, BEGV_BYTE, ZV, ZV_BYTE, true); + return Qnil; + } + + /* FIXME: It is not documented how to initialize the contents of the + context structure. This code cargo-cults from the existing + caller in src/analyze.c of GNU Diffutils, which appears to + work. */ + + ptrdiff_t diags = size_a + size_b + 3; + ptrdiff_t *buffer; + USE_SAFE_ALLOCA; + SAFE_NALLOCA (buffer, 2, diags); + /* Micro-optimization: Casting to size_t generates much better + code. */ + ptrdiff_t del_bytes = (size_t) size_a / CHAR_BIT + 1; + ptrdiff_t ins_bytes = (size_t) size_b / CHAR_BIT + 1; + struct context ctx = { + .buffer_a = a, + .buffer_b = b, + .deletions = SAFE_ALLOCA (del_bytes), + .insertions = SAFE_ALLOCA (ins_bytes), + .fdiag = buffer + size_b + 1, + .bdiag = buffer + diags + size_b + 1, + /* FIXME: Find a good number for .too_expensive. */ + .too_expensive = 1000000, + }; + memclear (ctx.deletions, del_bytes); + memclear (ctx.insertions, ins_bytes); + /* compareseq requires indices to be zero-based. We add BEGV back + later. */ + bool early_abort = compareseq (0, size_a, 0, size_b, false, &ctx); + /* Since we didn’t define EARLY_ABORT, we should never abort + early. */ + eassert (! early_abort); + SAFE_FREE (); + + Fundo_boundary (); + ptrdiff_t count = SPECPDL_INDEX (); + record_unwind_protect (save_excursion_restore, save_excursion_save ()); + + ptrdiff_t i = size_a; + ptrdiff_t j = size_b; + /* Walk backwards through the lists of changes. This was also + cargo-culted from src/analyze.c in GNU Diffutils. Because we + walk backwards, we don’t have to keep the positions in sync. */ + while (i >= 0 || j >= 0) + { + /* Check whether there is a change (insertion or deletion) + before the current position. */ + if ((i > 0 && bit_is_set (ctx.deletions, i - 1)) || + (j > 0 && bit_is_set (ctx.insertions, j - 1))) + { + ptrdiff_t end_a = min_a + i; + ptrdiff_t end_b = min_b + j; + /* Find the beginning of the current change run. */ + while (i > 0 && bit_is_set (ctx.deletions, i - 1)) + --i; + while (j > 0 && bit_is_set (ctx.insertions, j - 1)) + --j; + ptrdiff_t beg_a = min_a + i; + ptrdiff_t beg_b = min_b + j; + eassert (beg_a >= BEGV); + eassert (beg_b >= BUF_BEGV (b)); + eassert (beg_a <= end_a); + eassert (beg_b <= end_b); + eassert (end_a <= ZV); + eassert (end_b <= BUF_ZV (b)); + eassert (beg_a < end_a || beg_b < end_b); + if (beg_a < end_a) + del_range (beg_a, end_a); + if (beg_b < end_b) + { + SET_PT (beg_a); + Finsert_buffer_substring (source, make_natnum (beg_b), + make_natnum (end_b)); + } + } + --i; + --j; + } + + return unbind_to (count, Qnil); +} + +static void +set_bit (unsigned char *a, ptrdiff_t i) +{ + eassert (i >= 0); + /* Micro-optimization: Casting to size_t generates much better + code. */ + size_t j = i; + a[j / CHAR_BIT] |= (1 << (j % CHAR_BIT)); +} + +static bool +bit_is_set (const unsigned char *a, ptrdiff_t i) +{ + eassert (i >= 0); + /* Micro-optimization: Casting to size_t generates much better + code. */ + size_t j = i; + return a[j / CHAR_BIT] & (1 << (j % CHAR_BIT)); +} + +/* Return true if the characters at position POS_A of buffer + CTX->buffer_a and at position POS_B of buffer CTX->buffer_b are + equal. POS_A and POS_B are zero-based. Text properties are + ignored. */ + +static bool +buffer_chars_equal (struct context *ctx, + ptrdiff_t pos_a, ptrdiff_t pos_b) +{ + eassert (pos_a >= 0); + pos_a += BUF_BEGV (ctx->buffer_a); + eassert (pos_a >= BUF_BEGV (ctx->buffer_a)); + eassert (pos_a < BUF_ZV (ctx->buffer_a)); + + eassert (pos_b >= 0); + pos_b += BUF_BEGV (ctx->buffer_b); + eassert (pos_b >= BUF_BEGV (ctx->buffer_b)); + eassert (pos_b < BUF_ZV (ctx->buffer_b)); + + return BUF_FETCH_CHAR_AS_MULTIBYTE (ctx->buffer_a, pos_a) + == BUF_FETCH_CHAR_AS_MULTIBYTE (ctx->buffer_b, pos_b); +} + static void subst_char_in_region_unwind (Lisp_Object arg) @@ -3978,6 +4179,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) bool maybe_combine_byte; bool arg_intervals = false; USE_SAFE_ALLOCA; + sa_avail -= sizeof initial_buffer; /* Information recorded for each format spec. */ struct info @@ -5315,6 +5517,7 @@ functions if all the text being accessed has this property. */); defsubr (&Sinsert_buffer_substring); defsubr (&Scompare_buffer_substrings); + defsubr (&Sreplace_buffer_contents); defsubr (&Ssubst_char_in_region); defsubr (&Stranslate_region_internal); defsubr (&Sdelete_region); diff --git a/src/emacs-module.c b/src/emacs-module.c index de62329b3b8..2693a4529d6 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c @@ -170,6 +170,10 @@ static struct emacs_env_private global_env_private; internal_handler_##handlertype, \ internal_cleanup_##handlertype) +#if !__has_attribute (cleanup) + #error "__attribute__ ((cleanup)) not supported by this compiler; try GCC" +#endif + /* It is very important that pushing the handler doesn't itself raise a signal. Install the cleanup only after the handler has been pushed. Use __attribute__ ((cleanup)) to avoid @@ -764,6 +768,9 @@ funcall_module (Lisp_Object function, ptrdiff_t nargs, Lisp_Object *arglist) USE_SAFE_ALLOCA; ATTRIBUTE_MAY_ALIAS emacs_value *args; if (plain_values && ! module_assertions) + /* FIXME: The cast below is incorrect because the argument array + is not declared as const, so module functions can modify it. + Either declare it as const, or remove this branch. */ args = (emacs_value *) arglist; else { diff --git a/src/emacs-module.h.in b/src/emacs-module.h.in new file mode 100644 index 00000000000..339234fdb51 --- /dev/null +++ b/src/emacs-module.h.in @@ -0,0 +1,106 @@ +/* emacs-module.h - GNU Emacs module API. + +Copyright (C) 2015-2017 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/>. */ + +#ifndef EMACS_MODULE_H +#define EMACS_MODULE_H + +#include <stdint.h> +#include <stddef.h> + +#ifndef __cplusplus +#include <stdbool.h> +#endif + +#if defined __cplusplus && __cplusplus >= 201103L +# define EMACS_NOEXCEPT noexcept +#else +# define EMACS_NOEXCEPT +#endif + +#ifdef __has_attribute +#if __has_attribute(__nonnull__) +# define EMACS_ATTRIBUTE_NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#endif +#endif +#ifndef EMACS_ATTRIBUTE_NONNULL +# define EMACS_ATTRIBUTE_NONNULL(...) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Current environment. */ +typedef struct emacs_env_26 emacs_env; + +/* Opaque pointer representing an Emacs Lisp value. + BEWARE: Do not assume NULL is a valid value! */ +typedef struct emacs_value_tag *emacs_value; + +enum { emacs_variadic_function = -2 }; + +/* Struct passed to a module init function (emacs_module_init). */ +struct emacs_runtime +{ + /* Structure size (for version checking). */ + ptrdiff_t size; + + /* Private data; users should not touch this. */ + struct emacs_runtime_private *private_members; + + /* Return an environment pointer. */ + emacs_env *(*get_environment) (struct emacs_runtime *ert) + EMACS_ATTRIBUTE_NONNULL(1); +}; + + +/* Possible Emacs function call outcomes. */ +enum emacs_funcall_exit +{ + /* Function has returned normally. */ + emacs_funcall_exit_return = 0, + + /* Function has signaled an error using `signal'. */ + emacs_funcall_exit_signal = 1, + + /* Function has exit using `throw'. */ + emacs_funcall_exit_throw = 2, +}; + +struct emacs_env_25 +{ +@module_env_snippet_25@ +}; + +struct emacs_env_26 +{ +@module_env_snippet_25@ + +@module_env_snippet_26@ +}; + +/* Every module should define a function as follows. */ +extern int emacs_module_init (struct emacs_runtime *ert) + EMACS_ATTRIBUTE_NONNULL(1); + +#ifdef __cplusplus +} +#endif + +#endif /* EMACS_MODULE_H */ diff --git a/src/emacs.c b/src/emacs.c index b0892c7ebb8..da8df1bf1c7 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -223,8 +223,12 @@ Initialization options:\n\ --fg-daemon[=NAME] start a (named) server in the foreground\n\ --debug-init enable Emacs Lisp debugger for init file\n\ --display, -d DISPLAY use X server DISPLAY\n\ +", +#ifdef HAVE_MODULES + "\ --module-assertions assert behavior of dynamic modules\n\ ", +#endif "\ --no-build-details do not add build details such as time stamps\n\ --no-desktop do not load a saved desktop\n\ @@ -1733,7 +1737,9 @@ static const struct standard_args standard_args[] = { "-nl", "--no-loadup", 70, 0 }, { "-nsl", "--no-site-lisp", 65, 0 }, { "-no-build-details", "--no-build-details", 63, 0 }, +#ifdef HAVE_MODULES { "-module-assertions", "--module-assertions", 62, 0 }, +#endif /* -d must come last before the options handled in startup.el. */ { "-d", "--display", 60, 1 }, { "-display", 0, 60, 1 }, diff --git a/src/fileio.c b/src/fileio.c index c21056ee6f2..cb070029a9b 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -3306,11 +3306,7 @@ otherwise, if FILE2 does not exist, the answer is t. */) ? Qt : Qnil); } -#ifndef READ_BUF_SIZE -#define READ_BUF_SIZE (64 << 10) -#endif -/* Some buffer offsets are stored in 'int' variables. */ -verify (READ_BUF_SIZE <= INT_MAX); +enum { READ_BUF_SIZE = MAX_ALLOCA }; /* This function is called after Lisp functions to decide a coding system are called, or when they cause an error. Before they are diff --git a/src/gmalloc.c b/src/gmalloc.c index 49f1fafccc0..baaff58050f 100644 --- a/src/gmalloc.c +++ b/src/gmalloc.c @@ -77,11 +77,6 @@ extern void *(*__morecore) (ptrdiff_t); #ifdef HYBRID_MALLOC # include "sheap.h" # define DUMPED bss_sbrk_did_unexec -static bool -ALLOCATED_BEFORE_DUMPING (char *p) -{ - return bss_sbrk_buffer <= p && p < bss_sbrk_buffer + STATIC_HEAP_SIZE; -} #endif #ifdef __cplusplus @@ -133,8 +128,13 @@ typedef union /* Heap information for a busy block. */ struct { - /* Zero for a large (multiblock) object, or positive giving the - logarithm to the base two of the fragment size. */ + /* Zero for a block that is not one of ours (typically, + allocated by system malloc), positive for the log base 2 of + the fragment size of a fragmented block, -1 for the first + block of a multiblock object, and unspecified for later + blocks of that object. Type-0 blocks can be present + because the system malloc can be invoked by library + functions in an undumped Emacs. */ int type; union { @@ -144,8 +144,7 @@ typedef union size_t first; /* First free fragment of the block. */ } frag; /* For a large object, in its first block, this has the number - of blocks in the object. In the other blocks, this has a - negative number which says how far back the first block is. */ + of blocks in the object. */ ptrdiff_t size; } info; } busy; @@ -166,7 +165,7 @@ extern char *_heapbase; extern malloc_info *_heapinfo; /* Address to block number and vice versa. */ -#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) +#define BLOCK(A) ((size_t) ((char *) (A) - _heapbase) / BLOCKSIZE + 1) #define ADDRESS(B) ((void *) (((B) - 1) * BLOCKSIZE + _heapbase)) /* Current search index for the heap table. */ @@ -491,11 +490,8 @@ register_heapinfo (void) ++_chunks_used; /* Describe the heapinfo block itself in the heapinfo. */ - _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.type = -1; _heapinfo[block].busy.info.size = blocks; - /* Leave back-pointers for malloc_find_address. */ - while (--blocks > 0) - _heapinfo[block + blocks].busy.info.size = -blocks; } #ifdef USE_PTHREAD @@ -608,7 +604,7 @@ morecore_nolock (size_t size) PROTECT_MALLOC_STATE (0); /* Check if we need to grow the info table. */ - if ((size_t) BLOCK ((char *) result + size) > heapsize) + if (heapsize < BLOCK ((char *) result + size)) { /* Calculate the new _heapinfo table size. We do not account for the added blocks in the table itself, as we hope to place them in @@ -617,7 +613,7 @@ morecore_nolock (size_t size) newsize = heapsize; do newsize *= 2; - while ((size_t) BLOCK ((char *) result + size) > newsize); + while (newsize < BLOCK ((char *) result + size)); /* We must not reuse existing core for the new info table when called from realloc in the case of growing a large block, because the @@ -665,8 +661,7 @@ morecore_nolock (size_t size) /* Is it big enough to record status for its own space? If so, we win. */ - if ((size_t) BLOCK ((char *) newinfo - + newsize * sizeof (malloc_info)) + if (BLOCK ((char *) newinfo + newsize * sizeof (malloc_info)) < newsize) break; @@ -883,17 +878,11 @@ _malloc_internal_nolock (size_t size) --_chunks_free; } - _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.type = -1; _heapinfo[block].busy.info.size = blocks; ++_chunks_used; _bytes_used += blocks * BLOCKSIZE; _bytes_free -= blocks * BLOCKSIZE; - - /* Mark all the blocks of the object just allocated except for the - first with a negative number so you can find the first block by - adding that adjustment. */ - while (--blocks > 0) - _heapinfo[block + blocks].busy.info.size = -blocks; } PROTECT_MALLOC_STATE (1); @@ -1026,7 +1015,7 @@ _free_internal_nolock (void *ptr) type = _heapinfo[block].busy.type; switch (type) { - case 0: + case -1: /* Get as many statistics as early as we can. */ --_chunks_used; _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; @@ -1187,7 +1176,7 @@ _free_internal_nolock (void *ptr) prev->prev->next = next; if (next != NULL) next->prev = prev->prev; - _heapinfo[block].busy.type = 0; + _heapinfo[block].busy.type = -1; _heapinfo[block].busy.info.size = 1; /* Keep the statistics accurate. */ @@ -1326,7 +1315,7 @@ _realloc_internal_nolock (void *ptr, size_t size) type = _heapinfo[block].busy.type; switch (type) { - case 0: + case -1: /* Maybe reallocate a large block to a small fragment. */ if (size <= BLOCKSIZE / 2) { @@ -1346,7 +1335,7 @@ _realloc_internal_nolock (void *ptr, size_t size) { /* The new size is smaller; return excess memory to the free list. */ - _heapinfo[block + blocks].busy.type = 0; + _heapinfo[block + blocks].busy.type = -1; _heapinfo[block + blocks].busy.info.size = _heapinfo[block].busy.info.size - blocks; _heapinfo[block].busy.info.size = blocks; @@ -1721,6 +1710,20 @@ extern void *aligned_alloc (size_t alignment, size_t size); extern int posix_memalign (void **memptr, size_t alignment, size_t size); #endif +/* Assuming PTR was allocated via the hybrid malloc, return true if + PTR was allocated via gmalloc, not the system malloc. Also, return + true if _heaplimit is zero; this can happen temporarily when + gmalloc calls itself for internal use, and in that case PTR is + already known to be allocated via gmalloc. */ + +static bool +allocated_via_gmalloc (void *ptr) +{ + size_t block = BLOCK (ptr); + size_t blockmax = _heaplimit - 1; + return block <= blockmax && _heapinfo[block].busy.type != 0; +} + /* See the comments near the beginning of this file for explanations of the following functions. */ @@ -1743,13 +1746,10 @@ hybrid_calloc (size_t nmemb, size_t size) void hybrid_free (void *ptr) { - if (!DUMPED) + if (allocated_via_gmalloc (ptr)) gfree (ptr); - else if (!ALLOCATED_BEFORE_DUMPING (ptr)) + else free (ptr); - /* Otherwise the dumped emacs is trying to free something allocated - before dumping; do nothing. */ - return; } #if defined HAVE_ALIGNED_ALLOC || defined HAVE_POSIX_MEMALIGN @@ -1775,19 +1775,20 @@ hybrid_realloc (void *ptr, size_t size) int type; size_t block, oldsize; + if (!ptr) + return hybrid_malloc (size); + if (!allocated_via_gmalloc (ptr)) + return realloc (ptr, size); if (!DUMPED) return grealloc (ptr, size); - if (!ALLOCATED_BEFORE_DUMPING (ptr)) - return realloc (ptr, size); /* The dumped emacs is trying to realloc storage allocated before - dumping. We just malloc new space and copy the data. */ - if (size == 0 || ptr == NULL) - return malloc (size); - block = ((char *) ptr - _heapbase) / BLOCKSIZE + 1; + dumping via gmalloc. Allocate new space and copy the data. Do + not bother with gfree (ptr), as that would just waste time. */ + block = BLOCK (ptr); type = _heapinfo[block].busy.type; oldsize = - type == 0 ? _heapinfo[block].busy.info.size * BLOCKSIZE + type < 0 ? _heapinfo[block].busy.info.size * BLOCKSIZE : (size_t) 1 << type; result = malloc (size); if (result) diff --git a/src/image.c b/src/image.c index 429777ce511..aedec7954ee 100644 --- a/src/image.c +++ b/src/image.c @@ -2041,10 +2041,20 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, (*ximg)->info.bmiColors[0].rgbGreen = 0; (*ximg)->info.bmiColors[0].rgbRed = 0; (*ximg)->info.bmiColors[0].rgbReserved = 0; + /* bmiColors is a variable-length array declared by w32api + headers as bmiColors[1], which triggers a warning under + -Warray-bounds; shut that up. */ +# if GNUC_PREREQ (4, 4, 0) +# pragma GCC push_options +# pragma GCC diagnostic ignored "-Warray-bounds" +# endif (*ximg)->info.bmiColors[1].rgbBlue = 255; (*ximg)->info.bmiColors[1].rgbGreen = 255; (*ximg)->info.bmiColors[1].rgbRed = 255; (*ximg)->info.bmiColors[1].rgbReserved = 0; +# if GNUC_PREREQ (4, 4, 0) +# pragma GCC pop_options +# endif } hdc = get_frame_dc (f); diff --git a/src/lread.c b/src/lread.c index 3004e2b1915..b01cbd5c072 100644 --- a/src/lread.c +++ b/src/lread.c @@ -4863,11 +4863,12 @@ The remaining ENTRIES in the alist element describe the functions and variables defined in that file, the features provided, and the features required. Each entry has the form `(provide . FEATURE)', `(require . FEATURE)', `(defun . FUNCTION)', `(autoload . SYMBOL)', -`(defface . SYMBOL)', or `(t . SYMBOL)'. Entries like `(t . SYMBOL)' -may precede a `(defun . FUNCTION)' entry, and means that SYMBOL was an -autoload before this file redefined it as a function. In addition, -entries may also be single symbols, which means that SYMBOL was -defined by `defvar' or `defconst'. +`(defface . SYMBOL)', `(define-type . SYMBOL)', +`(cl-defmethod METHOD SPECIALIZERS)', or `(t . SYMBOL)'. +Entries like `(t . SYMBOL)' may precede a `(defun . FUNCTION)' entry, +and means that SYMBOL was an autoload before this file redefined it +as a function. In addition, entries may also be single symbols, +which means that symbol was defined by `defvar' or `defconst'. During preloading, the file name recorded is relative to the main Lisp directory. These file names are converted to absolute at startup. */); diff --git a/src/emacs-module.h b/src/module-env-25.h index ad102e6d843..17e67004b24 100644 --- a/src/emacs-module.h +++ b/src/module-env-25.h @@ -1,95 +1,3 @@ -/* emacs-module.h - GNU Emacs module API. - -Copyright (C) 2015-2017 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/>. */ - -#ifndef EMACS_MODULE_H -#define EMACS_MODULE_H - -#if ! (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) \ - && ! (defined __cplusplus && __cplusplus >= 199711L) -# error "This file requires at least C99 or C++98" -#endif - -#include <stdint.h> -#include <stddef.h> - -#ifndef __cplusplus -#include <stdbool.h> -#endif - -#if defined __cplusplus && __cplusplus >= 201103L -# define EMACS_NOEXCEPT noexcept -#else -# define EMACS_NOEXCEPT -#endif - -#ifdef __has_attribute -#if __has_attribute(__nonnull__) -# define EMACS_ATTRIBUTE_NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__))) -#endif -#endif -#ifndef EMACS_ATTRIBUTE_NONNULL -# define EMACS_ATTRIBUTE_NONNULL(...) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Current environment. */ -typedef struct emacs_env_25 emacs_env; - -/* Opaque pointer representing an Emacs Lisp value. - BEWARE: Do not assume NULL is a valid value! */ -typedef struct emacs_value_tag *emacs_value; - -enum { emacs_variadic_function = -2 }; - -/* Struct passed to a module init function (emacs_module_init). */ -struct emacs_runtime -{ - /* Structure size (for version checking). */ - ptrdiff_t size; - - /* Private data; users should not touch this. */ - struct emacs_runtime_private *private_members; - - /* Return an environment pointer. */ - emacs_env *(*get_environment) (struct emacs_runtime *ert) - EMACS_ATTRIBUTE_NONNULL(1); -}; - - -/* Possible Emacs function call outcomes. */ -enum emacs_funcall_exit -{ - /* Function has returned normally. */ - emacs_funcall_exit_return = 0, - - /* Function has signaled an error using `signal'. */ - emacs_funcall_exit_signal = 1, - - /* Function has exit using `throw'. */ - emacs_funcall_exit_throw = 2, -}; - -struct emacs_env_25 -{ /* Structure size (for version checking). */ ptrdiff_t size; @@ -230,18 +138,3 @@ struct emacs_env_25 ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vec) EMACS_ATTRIBUTE_NONNULL(1); - - /* Returns whether a quit is pending. */ - bool (*should_quit) (emacs_env *env) - EMACS_ATTRIBUTE_NONNULL(1); -}; - -/* Every module should define a function as follows. */ -extern int emacs_module_init (struct emacs_runtime *ert) - EMACS_ATTRIBUTE_NONNULL(1); - -#ifdef __cplusplus -} -#endif - -#endif /* EMACS_MODULE_H */ diff --git a/src/module-env-26.h b/src/module-env-26.h new file mode 100644 index 00000000000..1ab12d45c84 --- /dev/null +++ b/src/module-env-26.h @@ -0,0 +1,3 @@ + /* Returns whether a quit is pending. */ + bool (*should_quit) (emacs_env *env) + EMACS_ATTRIBUTE_NONNULL(1); diff --git a/src/unexelf.c b/src/unexelf.c index 7fad64fab17..5129784ade2 100644 --- a/src/unexelf.c +++ b/src/unexelf.c @@ -576,7 +576,17 @@ unexec (const char *new_name, const char *old_name) } /* This loop seeks out relocation sections for the data section, so - that it can undo relocations performed by the runtime loader. */ + that it can undo relocations performed by the runtime loader. + + The following approach does not work on x86 platforms that use + the GNU Gold linker, which can generate .rel.dyn relocation + sections containing R_386_32 entries that the following code does + not grok. Emacs works around this problem by avoiding C + constructs that generate such entries, which is horrible hack. + + FIXME: Presumably more problems like this will crop up as linkers + get fancier. We really need to stop assuming that Emacs can grok + arbitrary linker output. See Bug#27248. */ for (n = new_file_h->e_shnum; 0 < --n; ) { ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n); diff --git a/src/widget.c b/src/widget.c index d7ec7028517..585039d58c6 100644 --- a/src/widget.c +++ b/src/widget.c @@ -108,7 +108,7 @@ emacsFrameTranslations [] = "\ static EmacsFrameClassRec emacsFrameClassRec = { { /* core fields */ - /* superclass */ &widgetClassRec, + /* superclass */ 0, /* filled in by emacsFrameClass */ /* class_name */ (char *) "EmacsFrame", /* widget_size */ sizeof (EmacsFrameRec), /* class_initialize */ 0, @@ -146,7 +146,16 @@ static EmacsFrameClassRec emacsFrameClassRec = { } }; -WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec; +WidgetClass +emacsFrameClass (void) +{ + /* Set the superclass here rather than relying on static + initialization, to work around an unexelf.c bug on x86 platforms + that use the GNU Gold linker (Bug#27248). */ + emacsFrameClassRec.core_class.superclass = &widgetClassRec; + + return (WidgetClass) &emacsFrameClassRec; +} static void get_default_char_pixel_size (EmacsFrame ew, int *pixel_width, int *pixel_height) diff --git a/src/widget.h b/src/widget.h index 2c5fb61df2f..97dd6ab61de 100644 --- a/src/widget.h +++ b/src/widget.h @@ -90,7 +90,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ typedef struct _EmacsFrameRec *EmacsFrame; typedef struct _EmacsFrameClassRec *EmacsFrameClass; -extern WidgetClass emacsFrameClass; +extern WidgetClass emacsFrameClass (void); extern struct _DisplayContext *display_context; diff --git a/src/xfns.c b/src/xfns.c index e463391c74a..7be2253cc3b 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -2875,7 +2875,7 @@ x_window (struct frame *f, long window_prompting) XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++; XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++; XtSetArg (al[ac], XtNborderWidth, 0); ac++; - frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget, + frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass (), pane_widget, al, ac); f->output_data.x->edit_widget = frame_widget; |