summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in4
-rw-r--r--src/bidi.c14
-rw-r--r--src/buffer.h9
-rw-r--r--src/conf_post.h5
-rw-r--r--src/editfns.c203
-rw-r--r--src/emacs-module.c7
-rw-r--r--src/emacs-module.h.in106
-rw-r--r--src/emacs.c6
-rw-r--r--src/fileio.c6
-rw-r--r--src/gmalloc.c83
-rw-r--r--src/image.c10
-rw-r--r--src/lread.c11
-rw-r--r--src/module-env-25.h (renamed from src/emacs-module.h)107
-rw-r--r--src/module-env-26.h3
-rw-r--r--src/unexelf.c12
-rw-r--r--src/widget.c13
-rw-r--r--src/widget.h2
-rw-r--r--src/xfns.c2
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;