aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohn Wiegley2016-01-18 22:59:51 -0800
committerJohn Wiegley2016-01-18 22:59:51 -0800
commit1b76d9168336ede8976b980aeaed64ae2908501a (patch)
tree749e3c082a8575eee1888ba9e61e1aeaa70d0dbc /src
parentbca49307c8ea3f96d6eede375a7f42091ae5d5af (diff)
parent2e5a89fad151f8efa97aea3f400823a95bee6289 (diff)
downloademacs-1b76d9168336ede8976b980aeaed64ae2908501a.tar.gz
emacs-1b76d9168336ede8976b980aeaed64ae2908501a.zip
-
Diffstat (limited to 'src')
-rw-r--r--src/conf_post.h28
-rw-r--r--src/emacs-module.c3
-rw-r--r--src/fns.c3
-rw-r--r--src/gnutls.c10
-rw-r--r--src/gnutls.h1
-rw-r--r--src/sysdep.c66
-rw-r--r--src/window.c64
7 files changed, 121 insertions, 54 deletions
diff --git a/src/conf_post.h b/src/conf_post.h
index 98ff12e5a53..5c332a05a5c 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -51,10 +51,21 @@ typedef bool bool_bf;
51#endif 51#endif
52#endif 52#endif
53 53
54/* When not using Clang, assume its attributes and features are absent. */ 54/* Simulate __has_attribute on compilers that lack it. It is used only
55 on arguments like alloc_size that are handled in this simulation. */
55#ifndef __has_attribute 56#ifndef __has_attribute
56# define __has_attribute(a) false 57# define __has_attribute(a) __has_attribute_##a
57#endif 58# define __has_attribute_alloc_size (4 < __GNUC__ + (3 <= __GNUC_MINOR__))
59# define __has_attribute_cleanup (3 < __GNUC__ + (4 <= __GNUC_MINOR__))
60# define __has_attribute_externally_visible \
61 (4 < __GNUC__ + (1 <= __GNUC_MINOR__))
62# define __has_attribute_no_address_safety_analysis false
63# define __has_attribute_no_sanitize_address \
64 (4 < __GNUC__ + (8 <= __GNUC_MINOR__))
65#endif
66
67/* Simulate __has_feature on compilers that lack it. It is used only
68 to define ADDRESS_SANITIZER below. */
58#ifndef __has_feature 69#ifndef __has_feature
59# define __has_feature(a) false 70# define __has_feature(a) false
60#endif 71#endif
@@ -222,9 +233,7 @@ extern int emacs_setenv_TZ (char const *);
222#define NO_INLINE 233#define NO_INLINE
223#endif 234#endif
224 235
225#if (__clang__ \ 236#if __has_attribute (externally_visible)
226 ? __has_attribute (externally_visible) \
227 : (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)))
228#define EXTERNALLY_VISIBLE __attribute__((externally_visible)) 237#define EXTERNALLY_VISIBLE __attribute__((externally_visible))
229#else 238#else
230#define EXTERNALLY_VISIBLE 239#define EXTERNALLY_VISIBLE
@@ -253,9 +262,7 @@ extern int emacs_setenv_TZ (char const *);
253# define ATTRIBUTE_MALLOC 262# define ATTRIBUTE_MALLOC
254#endif 263#endif
255 264
256#if (__clang__ \ 265#if __has_attribute (alloc_size)
257 ? __has_attribute (alloc_size) \
258 : 4 < __GNUC__ + (3 <= __GNUC_MINOR__))
259# define ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args)) 266# define ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args))
260#else 267#else
261# define ATTRIBUTE_ALLOC_SIZE(args) 268# define ATTRIBUTE_ALLOC_SIZE(args)
@@ -278,8 +285,7 @@ extern int emacs_setenv_TZ (char const *);
278/* Attribute of functions whose code should not have addresses 285/* Attribute of functions whose code should not have addresses
279 sanitized. */ 286 sanitized. */
280 287
281#if (__has_attribute (no_sanitize_address) \ 288#if __has_attribute (no_sanitize_address)
282 || 4 < __GNUC__ + (8 <= __GNUC_MINOR__))
283# define ATTRIBUTE_NO_SANITIZE_ADDRESS \ 289# define ATTRIBUTE_NO_SANITIZE_ADDRESS \
284 __attribute__ ((no_sanitize_address)) ADDRESS_SANITIZER_WORKAROUND 290 __attribute__ ((no_sanitize_address)) ADDRESS_SANITIZER_WORKAROUND
285#elif __has_attribute (no_address_safety_analysis) 291#elif __has_attribute (no_address_safety_analysis)
diff --git a/src/emacs-module.c b/src/emacs-module.c
index b5e044e758f..79a077b3cb4 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -35,8 +35,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
35 35
36/* Feature tests. */ 36/* Feature tests. */
37 37
38/* True if __attribute__ ((cleanup (...))) works, false otherwise. */ 38#if __has_attribute (cleanup)
39#ifdef HAVE_VAR_ATTRIBUTE_CLEANUP
40enum { module_has_cleanup = true }; 39enum { module_has_cleanup = true };
41#else 40#else
42enum { module_has_cleanup = false }; 41enum { module_has_cleanup = false };
diff --git a/src/fns.c b/src/fns.c
index 977229b97b7..86ad333702e 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -50,7 +50,8 @@ All integers representable in Lisp, i.e. between `most-negative-fixnum'
50and `most-positive-fixnum', inclusive, are equally likely. 50and `most-positive-fixnum', inclusive, are equally likely.
51 51
52With positive integer LIMIT, return random number in interval [0,LIMIT). 52With positive integer LIMIT, return random number in interval [0,LIMIT).
53With argument t, set the random number seed from the current time and pid. 53With argument t, set the random number seed from the system's entropy
54pool if available, otherwise from less-random volatile data such as the time.
54With a string argument, set the seed based on the string's contents. 55With a string argument, set the seed based on the string's contents.
55Other values of LIMIT are ignored. 56Other values of LIMIT are ignored.
56 57
diff --git a/src/gnutls.c b/src/gnutls.c
index a1d058fcd48..01a5983d3b0 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -1112,15 +1112,17 @@ The return value is a property list with top-level keys :warnings and
1112/* Initialize global GnuTLS state to defaults. 1112/* Initialize global GnuTLS state to defaults.
1113 Call `gnutls-global-deinit' when GnuTLS usage is no longer needed. 1113 Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
1114 Return zero on success. */ 1114 Return zero on success. */
1115static Lisp_Object 1115Lisp_Object
1116emacs_gnutls_global_init (void) 1116emacs_gnutls_global_init (void)
1117{ 1117{
1118 int ret = GNUTLS_E_SUCCESS; 1118 int ret = GNUTLS_E_SUCCESS;
1119 1119
1120 if (!gnutls_global_initialized) 1120 if (!gnutls_global_initialized)
1121 ret = gnutls_global_init (); 1121 {
1122 1122 ret = gnutls_global_init ();
1123 gnutls_global_initialized = 1; 1123 if (ret == GNUTLS_E_SUCCESS)
1124 gnutls_global_initialized = 1;
1125 }
1124 1126
1125 return gnutls_make_error (ret); 1127 return gnutls_make_error (ret);
1126} 1128}
diff --git a/src/gnutls.h b/src/gnutls.h
index c4fe738bfa0..8e879c168bd 100644
--- a/src/gnutls.h
+++ b/src/gnutls.h
@@ -83,6 +83,7 @@ extern ptrdiff_t emacs_gnutls_record_check_pending (gnutls_session_t state);
83extern void emacs_gnutls_transport_set_errno (gnutls_session_t state, int err); 83extern void emacs_gnutls_transport_set_errno (gnutls_session_t state, int err);
84#endif 84#endif
85extern Lisp_Object emacs_gnutls_deinit (Lisp_Object); 85extern Lisp_Object emacs_gnutls_deinit (Lisp_Object);
86extern Lisp_Object emacs_gnutls_global_init (void);
86 87
87#endif 88#endif
88 89
diff --git a/src/sysdep.c b/src/sysdep.c
index e73acec733e..a86b53642f2 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -99,6 +99,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
99#include "process.h" 99#include "process.h"
100#include "cm.h" 100#include "cm.h"
101 101
102#include "gnutls.h"
103#if 0x020c00 <= GNUTLS_VERSION_NUMBER && !defined WINDOWSNT
104# include <gnutls/crypto.h>
105#else
106# define emacs_gnutls_global_init() Qnil
107# define gnutls_rnd(level, data, len) (-1)
108#endif
109
102#ifdef WINDOWSNT 110#ifdef WINDOWSNT
103#include <direct.h> 111#include <direct.h>
104/* In process.h which conflicts with the local copy. */ 112/* In process.h which conflicts with the local copy. */
@@ -2071,36 +2079,56 @@ init_signals (bool dumping)
2071# endif /* !HAVE_RANDOM */ 2079# endif /* !HAVE_RANDOM */
2072#endif /* !RAND_BITS */ 2080#endif /* !RAND_BITS */
2073 2081
2082#ifdef HAVE_RANDOM
2083typedef unsigned int random_seed;
2084static void set_random_seed (random_seed arg) { srandom (arg); }
2085#elif defined HAVE_LRAND48
2086/* Although srand48 uses a long seed, this is unsigned long to avoid
2087 undefined behavior on signed integer overflow in init_random. */
2088typedef unsigned long int random_seed;
2089static void set_random_seed (random_seed arg) { srand48 (arg); }
2090#else
2091typedef unsigned int random_seed;
2092static void set_random_seed (random_seed arg) { srand (arg); }
2093#endif
2094
2074void 2095void
2075seed_random (void *seed, ptrdiff_t seed_size) 2096seed_random (void *seed, ptrdiff_t seed_size)
2076{ 2097{
2077#if defined HAVE_RANDOM || ! defined HAVE_LRAND48 2098 random_seed arg = 0;
2078 unsigned int arg = 0;
2079#else
2080 long int arg = 0;
2081#endif
2082 unsigned char *argp = (unsigned char *) &arg; 2099 unsigned char *argp = (unsigned char *) &arg;
2083 unsigned char *seedp = seed; 2100 unsigned char *seedp = seed;
2084 ptrdiff_t i; 2101 for (ptrdiff_t i = 0; i < seed_size; i++)
2085 for (i = 0; i < seed_size; i++)
2086 argp[i % sizeof arg] ^= seedp[i]; 2102 argp[i % sizeof arg] ^= seedp[i];
2087#ifdef HAVE_RANDOM 2103 set_random_seed (arg);
2088 srandom (arg);
2089#else
2090# ifdef HAVE_LRAND48
2091 srand48 (arg);
2092# else
2093 srand (arg);
2094# endif
2095#endif
2096} 2104}
2097 2105
2098void 2106void
2099init_random (void) 2107init_random (void)
2100{ 2108{
2101 struct timespec t = current_timespec (); 2109 random_seed v;
2102 uintmax_t v = getpid () ^ t.tv_sec ^ t.tv_nsec; 2110 if (! (EQ (emacs_gnutls_global_init (), Qt)
2103 seed_random (&v, sizeof v); 2111 && gnutls_rnd (GNUTLS_RND_NONCE, &v, sizeof v) == 0))
2112 {
2113 bool success = false;
2114#ifndef WINDOWSNT
2115 int fd = emacs_open ("/dev/urandom", O_RDONLY | O_BINARY, 0);
2116 if (0 <= fd)
2117 {
2118 success = emacs_read (fd, &v, sizeof v) == sizeof v;
2119 emacs_close (fd);
2120 }
2121#else
2122 success = w32_init_random (&v, sizeof v) == 0;
2123#endif
2124 if (! success)
2125 {
2126 /* Fall back to current time value + PID. */
2127 struct timespec t = current_timespec ();
2128 v = getpid () ^ t.tv_sec ^ t.tv_nsec;
2129 }
2130 }
2131 set_random_seed (v);
2104} 2132}
2105 2133
2106/* 2134/*
diff --git a/src/window.c b/src/window.c
index bb414e7d311..4aeb8b39a70 100644
--- a/src/window.c
+++ b/src/window.c
@@ -4979,27 +4979,34 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
4979 4979
4980 if (n > 0) 4980 if (n > 0)
4981 { 4981 {
4982 int last_y = it.last_visible_y - this_scroll_margin - 1;
4983
4982 /* We moved the window start towards ZV, so PT may be now 4984 /* We moved the window start towards ZV, so PT may be now
4983 in the scroll margin at the top. */ 4985 in the scroll margin at the top. */
4984 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS); 4986 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4985 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin 4987 if (IT_CHARPOS (it) == PT
4988 && it.current_y >= this_scroll_margin
4989 && it.current_y <= last_y - WINDOW_HEADER_LINE_HEIGHT (w)
4986 && (NILP (Vscroll_preserve_screen_position) 4990 && (NILP (Vscroll_preserve_screen_position)
4987 || EQ (Vscroll_preserve_screen_position, Qt))) 4991 || EQ (Vscroll_preserve_screen_position, Qt)))
4988 /* We found PT at a legitimate height. Leave it alone. */ 4992 /* We found PT at a legitimate height. Leave it alone. */
4989 ; 4993 ;
4990 else if (window_scroll_pixel_based_preserve_y >= 0)
4991 {
4992 /* If we have a header line, take account of it.
4993 This is necessary because we set it.current_y to 0, above. */
4994 move_it_to (&it, -1,
4995 window_scroll_pixel_based_preserve_x,
4996 (window_scroll_pixel_based_preserve_y
4997 - WINDOW_WANTS_HEADER_LINE_P (w)),
4998 -1, MOVE_TO_Y | MOVE_TO_X);
4999 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5000 }
5001 else 4994 else
5002 { 4995 {
4996 if (window_scroll_pixel_based_preserve_y >= 0)
4997 {
4998 /* Don't enter the scroll margin at the end of the window. */
4999 int goal_y = min (last_y, window_scroll_pixel_based_preserve_y);
5000
5001 /* If we have a header line, take account of it. This
5002 is necessary because we set it.current_y to 0, above. */
5003 move_it_to (&it, -1,
5004 window_scroll_pixel_based_preserve_x,
5005 goal_y - WINDOW_HEADER_LINE_HEIGHT (w),
5006 -1, MOVE_TO_Y | MOVE_TO_X);
5007 }
5008
5009 /* Get out of the scroll margin at the top of the window. */
5003 while (it.current_y < this_scroll_margin) 5010 while (it.current_y < this_scroll_margin)
5004 { 5011 {
5005 int prev = it.current_y; 5012 int prev = it.current_y;
@@ -5023,7 +5030,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
5023 /* We moved the window start towards BEGV, so PT may be now 5030 /* We moved the window start towards BEGV, so PT may be now
5024 in the scroll margin at the bottom. */ 5031 in the scroll margin at the bottom. */
5025 move_it_to (&it, PT, -1, 5032 move_it_to (&it, PT, -1,
5026 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w) 5033 (it.last_visible_y - WINDOW_HEADER_LINE_HEIGHT (w)
5027 - this_scroll_margin - 1), 5034 - this_scroll_margin - 1),
5028 -1, 5035 -1,
5029 MOVE_TO_POS | MOVE_TO_Y); 5036 MOVE_TO_POS | MOVE_TO_Y);
@@ -5074,14 +5081,20 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
5074 ; 5081 ;
5075 else if (window_scroll_pixel_based_preserve_y >= 0) 5082 else if (window_scroll_pixel_based_preserve_y >= 0)
5076 { 5083 {
5084 int goal_y = min (it.last_visible_y - this_scroll_margin - 1,
5085 window_scroll_pixel_based_preserve_y);
5086
5087 /* Don't let the preserved screen Y coordinate put us inside
5088 any of the two margins. */
5089 if (goal_y < this_scroll_margin)
5090 goal_y = this_scroll_margin;
5077 SET_TEXT_POS_FROM_MARKER (start, w->start); 5091 SET_TEXT_POS_FROM_MARKER (start, w->start);
5078 start_display (&it, w, start); 5092 start_display (&it, w, start);
5079 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT 5093 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5080 here because we called start_display again and did not 5094 here because we called start_display again and did not
5081 alter it.current_y this time. */ 5095 alter it.current_y this time. */
5082 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x, 5096 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
5083 window_scroll_pixel_based_preserve_y, -1, 5097 goal_y, -1, MOVE_TO_Y | MOVE_TO_X);
5084 MOVE_TO_Y | MOVE_TO_X);
5085 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it)); 5098 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5086 } 5099 }
5087 else 5100 else
@@ -5197,6 +5210,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
5197 w->force_start = true; 5210 w->force_start = true;
5198 5211
5199 if (!NILP (Vscroll_preserve_screen_position) 5212 if (!NILP (Vscroll_preserve_screen_position)
5213 && this_scroll_margin == 0
5200 && (whole || !EQ (Vscroll_preserve_screen_position, Qt))) 5214 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5201 { 5215 {
5202 SET_PT_BOTH (pos, pos_byte); 5216 SET_PT_BOTH (pos, pos_byte);
@@ -5222,8 +5236,16 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
5222 marker_byte_position (opoint_marker)); 5236 marker_byte_position (opoint_marker));
5223 else if (!NILP (Vscroll_preserve_screen_position)) 5237 else if (!NILP (Vscroll_preserve_screen_position))
5224 { 5238 {
5239 int nlines = window_scroll_preserve_vpos;
5240
5225 SET_PT_BOTH (pos, pos_byte); 5241 SET_PT_BOTH (pos, pos_byte);
5226 Fvertical_motion (original_pos, window, Qnil); 5242 if (window_scroll_preserve_vpos < this_scroll_margin)
5243 nlines = this_scroll_margin;
5244 else if (window_scroll_preserve_vpos
5245 >= w->total_lines - this_scroll_margin)
5246 nlines = w->total_lines - this_scroll_margin - 1;
5247 Fvertical_motion (Fcons (make_number (window_scroll_preserve_hpos),
5248 make_number (nlines)), window, Qnil);
5227 } 5249 }
5228 else 5250 else
5229 SET_PT (top_margin); 5251 SET_PT (top_margin);
@@ -5249,8 +5271,16 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
5249 { 5271 {
5250 if (!NILP (Vscroll_preserve_screen_position)) 5272 if (!NILP (Vscroll_preserve_screen_position))
5251 { 5273 {
5274 int nlines = window_scroll_preserve_vpos;
5275
5252 SET_PT_BOTH (pos, pos_byte); 5276 SET_PT_BOTH (pos, pos_byte);
5253 Fvertical_motion (original_pos, window, Qnil); 5277 if (window_scroll_preserve_vpos < this_scroll_margin)
5278 nlines = this_scroll_margin;
5279 else if (window_scroll_preserve_vpos
5280 >= ht - this_scroll_margin)
5281 nlines = ht - this_scroll_margin - 1;
5282 Fvertical_motion (Fcons (make_number (window_scroll_preserve_hpos),
5283 make_number (nlines)), window, Qnil);
5254 } 5284 }
5255 else 5285 else
5256 Fvertical_motion (make_number (-1), window, Qnil); 5286 Fvertical_motion (make_number (-1), window, Qnil);