diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/buffer.c | 8 | ||||
| -rw-r--r-- | src/conf_post.h | 28 | ||||
| -rw-r--r-- | src/emacs-module.c | 3 | ||||
| -rw-r--r-- | src/fns.c | 3 | ||||
| -rw-r--r-- | src/gnutls.c | 10 | ||||
| -rw-r--r-- | src/gnutls.h | 1 | ||||
| -rw-r--r-- | src/keyboard.c | 80 | ||||
| -rw-r--r-- | src/sysdep.c | 66 | ||||
| -rw-r--r-- | src/w32.c | 62 | ||||
| -rw-r--r-- | src/w32.h | 1 | ||||
| -rw-r--r-- | src/w32fns.c | 42 | ||||
| -rw-r--r-- | src/w32heap.c | 89 | ||||
| -rw-r--r-- | src/w32proc.c | 7 | ||||
| -rw-r--r-- | src/window.c | 64 |
14 files changed, 336 insertions, 128 deletions
diff --git a/src/buffer.c b/src/buffer.c index 1468e7a2be1..4df77a181d6 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -5630,13 +5630,7 @@ Decimal digits after the % specify field width to which to pad. */); | |||
| 5630 | doc: /* Symbol for current buffer's major mode. | 5630 | doc: /* Symbol for current buffer's major mode. |
| 5631 | The default value (normally `fundamental-mode') affects new buffers. | 5631 | The default value (normally `fundamental-mode') affects new buffers. |
| 5632 | A value of nil means to use the current buffer's major mode, provided | 5632 | A value of nil means to use the current buffer's major mode, provided |
| 5633 | it is not marked as "special". | 5633 | it is not marked as "special". */); |
| 5634 | |||
| 5635 | When a mode is used by default, `find-file' switches to it before it | ||
| 5636 | reads the contents into the buffer and before it finishes setting up | ||
| 5637 | the buffer. Thus, the mode and its hooks should not expect certain | ||
| 5638 | variables such as `buffer-read-only' and `buffer-file-coding-system' | ||
| 5639 | to be set up. */); | ||
| 5640 | 5634 | ||
| 5641 | DEFVAR_PER_BUFFER ("mode-name", &BVAR (current_buffer, mode_name), | 5635 | DEFVAR_PER_BUFFER ("mode-name", &BVAR (current_buffer, mode_name), |
| 5642 | Qnil, | 5636 | Qnil, |
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 | ||
| 40 | enum { module_has_cleanup = true }; | 39 | enum { module_has_cleanup = true }; |
| 41 | #else | 40 | #else |
| 42 | enum { module_has_cleanup = false }; | 41 | enum { module_has_cleanup = false }; |
| @@ -50,7 +50,8 @@ All integers representable in Lisp, i.e. between `most-negative-fixnum' | |||
| 50 | and `most-positive-fixnum', inclusive, are equally likely. | 50 | and `most-positive-fixnum', inclusive, are equally likely. |
| 51 | 51 | ||
| 52 | With positive integer LIMIT, return random number in interval [0,LIMIT). | 52 | With positive integer LIMIT, return random number in interval [0,LIMIT). |
| 53 | With argument t, set the random number seed from the current time and pid. | 53 | With argument t, set the random number seed from the system's entropy |
| 54 | pool if available, otherwise from less-random volatile data such as the time. | ||
| 54 | With a string argument, set the seed based on the string's contents. | 55 | With a string argument, set the seed based on the string's contents. |
| 55 | Other values of LIMIT are ignored. | 56 | Other 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. */ |
| 1115 | static Lisp_Object | 1115 | Lisp_Object |
| 1116 | emacs_gnutls_global_init (void) | 1116 | emacs_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); | |||
| 83 | extern void emacs_gnutls_transport_set_errno (gnutls_session_t state, int err); | 83 | extern void emacs_gnutls_transport_set_errno (gnutls_session_t state, int err); |
| 84 | #endif | 84 | #endif |
| 85 | extern Lisp_Object emacs_gnutls_deinit (Lisp_Object); | 85 | extern Lisp_Object emacs_gnutls_deinit (Lisp_Object); |
| 86 | extern Lisp_Object emacs_gnutls_global_init (void); | ||
| 86 | 87 | ||
| 87 | #endif | 88 | #endif |
| 88 | 89 | ||
diff --git a/src/keyboard.c b/src/keyboard.c index c3aa76af518..c8a9728e896 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -64,6 +64,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 64 | #include <unistd.h> | 64 | #include <unistd.h> |
| 65 | #include <fcntl.h> | 65 | #include <fcntl.h> |
| 66 | 66 | ||
| 67 | #include <ignore-value.h> | ||
| 68 | |||
| 67 | #ifdef HAVE_WINDOW_SYSTEM | 69 | #ifdef HAVE_WINDOW_SYSTEM |
| 68 | #include TERM_HEADER | 70 | #include TERM_HEADER |
| 69 | #endif /* HAVE_WINDOW_SYSTEM */ | 71 | #endif /* HAVE_WINDOW_SYSTEM */ |
| @@ -1234,9 +1236,6 @@ static void adjust_point_for_property (ptrdiff_t, bool); | |||
| 1234 | Lisp_Object | 1236 | Lisp_Object |
| 1235 | command_loop_1 (void) | 1237 | command_loop_1 (void) |
| 1236 | { | 1238 | { |
| 1237 | Lisp_Object cmd; | ||
| 1238 | Lisp_Object keybuf[30]; | ||
| 1239 | int i; | ||
| 1240 | EMACS_INT prev_modiff = 0; | 1239 | EMACS_INT prev_modiff = 0; |
| 1241 | struct buffer *prev_buffer = NULL; | 1240 | struct buffer *prev_buffer = NULL; |
| 1242 | bool already_adjusted = 0; | 1241 | bool already_adjusted = 0; |
| @@ -1280,6 +1279,10 @@ command_loop_1 (void) | |||
| 1280 | 1279 | ||
| 1281 | while (1) | 1280 | while (1) |
| 1282 | { | 1281 | { |
| 1282 | Lisp_Object cmd; | ||
| 1283 | Lisp_Object keybuf[30]; | ||
| 1284 | int i; | ||
| 1285 | |||
| 1283 | if (! FRAME_LIVE_P (XFRAME (selected_frame))) | 1286 | if (! FRAME_LIVE_P (XFRAME (selected_frame))) |
| 1284 | Fkill_emacs (Qnil); | 1287 | Fkill_emacs (Qnil); |
| 1285 | 1288 | ||
| @@ -10205,6 +10208,21 @@ deliver_interrupt_signal (int sig) | |||
| 10205 | deliver_process_signal (sig, handle_interrupt_signal); | 10208 | deliver_process_signal (sig, handle_interrupt_signal); |
| 10206 | } | 10209 | } |
| 10207 | 10210 | ||
| 10211 | /* Output MSG directly to standard output, without buffering. Ignore | ||
| 10212 | failures. This is safe in a signal handler. */ | ||
| 10213 | static void | ||
| 10214 | write_stdout (char const *msg) | ||
| 10215 | { | ||
| 10216 | ignore_value (write (STDOUT_FILENO, msg, strlen (msg))); | ||
| 10217 | } | ||
| 10218 | |||
| 10219 | /* Read a byte from stdin, without buffering. Safe in signal handlers. */ | ||
| 10220 | static int | ||
| 10221 | read_stdin (void) | ||
| 10222 | { | ||
| 10223 | char c; | ||
| 10224 | return read (STDIN_FILENO, &c, 1) == 1 ? c : EOF; | ||
| 10225 | } | ||
| 10208 | 10226 | ||
| 10209 | /* If Emacs is stuck because `inhibit-quit' is true, then keep track | 10227 | /* If Emacs is stuck because `inhibit-quit' is true, then keep track |
| 10210 | of the number of times C-g has been requested. If C-g is pressed | 10228 | of the number of times C-g has been requested. If C-g is pressed |
| @@ -10241,9 +10259,9 @@ handle_interrupt (bool in_signal_handler) | |||
| 10241 | sigemptyset (&blocked); | 10259 | sigemptyset (&blocked); |
| 10242 | sigaddset (&blocked, SIGINT); | 10260 | sigaddset (&blocked, SIGINT); |
| 10243 | pthread_sigmask (SIG_BLOCK, &blocked, 0); | 10261 | pthread_sigmask (SIG_BLOCK, &blocked, 0); |
| 10262 | fflush (stdout); | ||
| 10244 | } | 10263 | } |
| 10245 | 10264 | ||
| 10246 | fflush (stdout); | ||
| 10247 | reset_all_sys_modes (); | 10265 | reset_all_sys_modes (); |
| 10248 | 10266 | ||
| 10249 | #ifdef SIGTSTP | 10267 | #ifdef SIGTSTP |
| @@ -10259,8 +10277,9 @@ handle_interrupt (bool in_signal_handler) | |||
| 10259 | /* Perhaps should really fork an inferior shell? | 10277 | /* Perhaps should really fork an inferior shell? |
| 10260 | But that would not provide any way to get back | 10278 | But that would not provide any way to get back |
| 10261 | to the original shell, ever. */ | 10279 | to the original shell, ever. */ |
| 10262 | printf ("No support for stopping a process on this operating system;\n"); | 10280 | write_stdout ("No support for stopping a process" |
| 10263 | printf ("you can continue or abort.\n"); | 10281 | " on this operating system;\n" |
| 10282 | "you can continue or abort.\n"); | ||
| 10264 | #endif /* not SIGTSTP */ | 10283 | #endif /* not SIGTSTP */ |
| 10265 | #ifdef MSDOS | 10284 | #ifdef MSDOS |
| 10266 | /* We must remain inside the screen area when the internal terminal | 10285 | /* We must remain inside the screen area when the internal terminal |
| @@ -10271,46 +10290,49 @@ handle_interrupt (bool in_signal_handler) | |||
| 10271 | the code used for auto-saving doesn't cope with the mark bit. */ | 10290 | the code used for auto-saving doesn't cope with the mark bit. */ |
| 10272 | if (!gc_in_progress) | 10291 | if (!gc_in_progress) |
| 10273 | { | 10292 | { |
| 10274 | printf ("Auto-save? (y or n) "); | 10293 | write_stdout ("Auto-save? (y or n) "); |
| 10275 | fflush (stdout); | 10294 | c = read_stdin (); |
| 10276 | if (((c = getchar ()) & ~040) == 'Y') | 10295 | if ((c & 040) == 'Y') |
| 10277 | { | 10296 | { |
| 10278 | Fdo_auto_save (Qt, Qnil); | 10297 | Fdo_auto_save (Qt, Qnil); |
| 10279 | #ifdef MSDOS | 10298 | #ifdef MSDOS |
| 10280 | printf ("\r\nAuto-save done"); | 10299 | write_stdout ("\r\nAuto-save done"); |
| 10281 | #else /* not MSDOS */ | 10300 | #else |
| 10282 | printf ("Auto-save done\n"); | 10301 | write_stdout ("Auto-save done\n"); |
| 10283 | #endif /* not MSDOS */ | 10302 | #endif |
| 10284 | } | 10303 | } |
| 10285 | while (c != '\n') c = getchar (); | 10304 | while (c != '\n') |
| 10305 | c = read_stdin (); | ||
| 10286 | } | 10306 | } |
| 10287 | else | 10307 | else |
| 10288 | { | 10308 | { |
| 10289 | /* During GC, it must be safe to reenable quitting again. */ | 10309 | /* During GC, it must be safe to reenable quitting again. */ |
| 10290 | Vinhibit_quit = Qnil; | 10310 | Vinhibit_quit = Qnil; |
| 10311 | write_stdout | ||
| 10312 | ( | ||
| 10291 | #ifdef MSDOS | 10313 | #ifdef MSDOS |
| 10292 | printf ("\r\n"); | 10314 | "\r\n" |
| 10293 | #endif /* not MSDOS */ | 10315 | #endif |
| 10294 | printf ("Garbage collection in progress; cannot auto-save now\r\n"); | 10316 | "Garbage collection in progress; cannot auto-save now\r\n" |
| 10295 | printf ("but will instead do a real quit after garbage collection ends\r\n"); | 10317 | "but will instead do a real quit" |
| 10296 | fflush (stdout); | 10318 | " after garbage collection ends\r\n"); |
| 10297 | } | 10319 | } |
| 10298 | 10320 | ||
| 10299 | #ifdef MSDOS | 10321 | #ifdef MSDOS |
| 10300 | printf ("\r\nAbort? (y or n) "); | 10322 | write_stdout ("\r\nAbort? (y or n) "); |
| 10301 | #else /* not MSDOS */ | 10323 | #else |
| 10302 | printf ("Abort (and dump core)? (y or n) "); | 10324 | write_stdout ("Abort (and dump core)? (y or n) "); |
| 10303 | #endif /* not MSDOS */ | 10325 | #endif |
| 10304 | fflush (stdout); | 10326 | c = read_stdin (); |
| 10305 | if (((c = getchar ()) & ~040) == 'Y') | 10327 | if ((c & ~040) == 'Y') |
| 10306 | emacs_abort (); | 10328 | emacs_abort (); |
| 10307 | while (c != '\n') c = getchar (); | 10329 | while (c != '\n') |
| 10330 | c = read_stdin (); | ||
| 10308 | #ifdef MSDOS | 10331 | #ifdef MSDOS |
| 10309 | printf ("\r\nContinuing...\r\n"); | 10332 | write_stdout ("\r\nContinuing...\r\n"); |
| 10310 | #else /* not MSDOS */ | 10333 | #else /* not MSDOS */ |
| 10311 | printf ("Continuing...\n"); | 10334 | write_stdout ("Continuing...\n"); |
| 10312 | #endif /* not MSDOS */ | 10335 | #endif /* not MSDOS */ |
| 10313 | fflush (stdout); | ||
| 10314 | init_all_sys_modes (); | 10336 | init_all_sys_modes (); |
| 10315 | } | 10337 | } |
| 10316 | else | 10338 | else |
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 | ||
| 2083 | typedef unsigned int random_seed; | ||
| 2084 | static 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. */ | ||
| 2088 | typedef unsigned long int random_seed; | ||
| 2089 | static void set_random_seed (random_seed arg) { srand48 (arg); } | ||
| 2090 | #else | ||
| 2091 | typedef unsigned int random_seed; | ||
| 2092 | static void set_random_seed (random_seed arg) { srand (arg); } | ||
| 2093 | #endif | ||
| 2094 | |||
| 2074 | void | 2095 | void |
| 2075 | seed_random (void *seed, ptrdiff_t seed_size) | 2096 | seed_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 | ||
| 2098 | void | 2106 | void |
| 2099 | init_random (void) | 2107 | init_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 | /* |
| @@ -484,6 +484,7 @@ typedef DWORD (WINAPI *GetAdaptersInfo_Proc) ( | |||
| 484 | 484 | ||
| 485 | int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int); | 485 | int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int); |
| 486 | int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL); | 486 | int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL); |
| 487 | DWORD multiByteToWideCharFlags; | ||
| 487 | 488 | ||
| 488 | /* ** A utility function ** */ | 489 | /* ** A utility function ** */ |
| 489 | static BOOL | 490 | static BOOL |
| @@ -1550,8 +1551,8 @@ codepage_for_filenames (CPINFO *cp_info) | |||
| 1550 | int | 1551 | int |
| 1551 | filename_to_utf16 (const char *fn_in, wchar_t *fn_out) | 1552 | filename_to_utf16 (const char *fn_in, wchar_t *fn_out) |
| 1552 | { | 1553 | { |
| 1553 | int result = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, fn_in, -1, | 1554 | int result = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, fn_in, |
| 1554 | fn_out, MAX_PATH); | 1555 | -1, fn_out, MAX_PATH); |
| 1555 | 1556 | ||
| 1556 | if (!result) | 1557 | if (!result) |
| 1557 | { | 1558 | { |
| @@ -1641,8 +1642,8 @@ filename_from_ansi (const char *fn_in, char *fn_out) | |||
| 1641 | { | 1642 | { |
| 1642 | wchar_t fn_utf16[MAX_PATH]; | 1643 | wchar_t fn_utf16[MAX_PATH]; |
| 1643 | int codepage = codepage_for_filenames (NULL); | 1644 | int codepage = codepage_for_filenames (NULL); |
| 1644 | int result = pMultiByteToWideChar (codepage, MB_ERR_INVALID_CHARS, fn_in, -1, | 1645 | int result = pMultiByteToWideChar (codepage, multiByteToWideCharFlags, fn_in, |
| 1645 | fn_utf16, MAX_PATH); | 1646 | -1, fn_utf16, MAX_PATH); |
| 1646 | 1647 | ||
| 1647 | if (!result) | 1648 | if (!result) |
| 1648 | { | 1649 | { |
| @@ -8043,14 +8044,19 @@ pipe2 (int * phandles, int pipe2_flags) | |||
| 8043 | { | 8044 | { |
| 8044 | int rc; | 8045 | int rc; |
| 8045 | unsigned flags; | 8046 | unsigned flags; |
| 8047 | unsigned pipe_size = 0; | ||
| 8046 | 8048 | ||
| 8047 | eassert (pipe2_flags == (O_BINARY | O_CLOEXEC)); | 8049 | eassert (pipe2_flags == (O_BINARY | O_CLOEXEC)); |
| 8048 | 8050 | ||
| 8051 | /* Allow Lisp to override the default buffer size of the pipe. */ | ||
| 8052 | if (w32_pipe_buffer_size > 0 && w32_pipe_buffer_size < UINT_MAX) | ||
| 8053 | pipe_size = w32_pipe_buffer_size; | ||
| 8054 | |||
| 8049 | /* make pipe handles non-inheritable; when we spawn a child, we | 8055 | /* make pipe handles non-inheritable; when we spawn a child, we |
| 8050 | replace the relevant handle with an inheritable one. Also put | 8056 | replace the relevant handle with an inheritable one. Also put |
| 8051 | pipes into binary mode; we will do text mode translation ourselves | 8057 | pipes into binary mode; we will do text mode translation ourselves |
| 8052 | if required. */ | 8058 | if required. */ |
| 8053 | rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY); | 8059 | rc = _pipe (phandles, pipe_size, _O_NOINHERIT | _O_BINARY); |
| 8054 | 8060 | ||
| 8055 | if (rc == 0) | 8061 | if (rc == 0) |
| 8056 | { | 8062 | { |
| @@ -8632,15 +8638,35 @@ sys_write (int fd, const void * buffer, unsigned int count) | |||
| 8632 | http://thread.gmane.org/gmane.comp.version-control.git/145294 | 8638 | http://thread.gmane.org/gmane.comp.version-control.git/145294 |
| 8633 | in the git mailing list. */ | 8639 | in the git mailing list. */ |
| 8634 | const unsigned char *p = buffer; | 8640 | const unsigned char *p = buffer; |
| 8635 | const unsigned chunk = 30 * 1024 * 1024; | 8641 | const bool is_pipe = (fd < MAXDESC |
| 8642 | && ((fd_info[fd].flags & (FILE_PIPE | FILE_NDELAY)) | ||
| 8643 | == (FILE_PIPE | FILE_NDELAY))); | ||
| 8644 | /* Some programs, notably Node.js's node.exe, seem to never | ||
| 8645 | completely empty the pipe, so writing more than the size of | ||
| 8646 | the pipe's buffer always returns ENOSPC, and we loop forever | ||
| 8647 | between send_process and here. As a workaround, write no | ||
| 8648 | more than the pipe's buffer can hold. */ | ||
| 8649 | DWORD pipe_buffer_size; | ||
| 8650 | if (is_pipe) | ||
| 8651 | { | ||
| 8652 | if (!GetNamedPipeInfo ((HANDLE)_get_osfhandle (fd), | ||
| 8653 | NULL, &pipe_buffer_size, NULL, NULL)) | ||
| 8654 | { | ||
| 8655 | DebPrint (("GetNamedPipeInfo: error %u\n", GetLastError ())); | ||
| 8656 | pipe_buffer_size = 4096; | ||
| 8657 | } | ||
| 8658 | } | ||
| 8659 | const unsigned chunk = is_pipe ? pipe_buffer_size : 30 * 1024 * 1024; | ||
| 8636 | 8660 | ||
| 8637 | nchars = 0; | 8661 | nchars = 0; |
| 8662 | errno = 0; | ||
| 8638 | while (count > 0) | 8663 | while (count > 0) |
| 8639 | { | 8664 | { |
| 8640 | unsigned this_chunk = count < chunk ? count : chunk; | 8665 | unsigned this_chunk = count < chunk ? count : chunk; |
| 8641 | int n = _write (fd, p, this_chunk); | 8666 | int n = _write (fd, p, this_chunk); |
| 8642 | 8667 | ||
| 8643 | nchars += n; | 8668 | if (n > 0) |
| 8669 | nchars += n; | ||
| 8644 | if (n < 0) | 8670 | if (n < 0) |
| 8645 | { | 8671 | { |
| 8646 | /* When there's no buffer space in a pipe that is in the | 8672 | /* When there's no buffer space in a pipe that is in the |
| @@ -8654,12 +8680,10 @@ sys_write (int fd, const void * buffer, unsigned int count) | |||
| 8654 | avoiding deadlock whereby each side of the pipe is | 8680 | avoiding deadlock whereby each side of the pipe is |
| 8655 | blocked on write, waiting for the other party to read | 8681 | blocked on write, waiting for the other party to read |
| 8656 | its end of the pipe. */ | 8682 | its end of the pipe. */ |
| 8657 | if (errno == ENOSPC | 8683 | if (errno == ENOSPC && is_pipe) |
| 8658 | && fd < MAXDESC | ||
| 8659 | && ((fd_info[fd].flags & (FILE_PIPE | FILE_NDELAY)) | ||
| 8660 | == (FILE_PIPE | FILE_NDELAY))) | ||
| 8661 | errno = EAGAIN; | 8684 | errno = EAGAIN; |
| 8662 | nchars = n; | 8685 | if (nchars == 0) |
| 8686 | nchars = -1; | ||
| 8663 | break; | 8687 | break; |
| 8664 | } | 8688 | } |
| 8665 | else if (n < this_chunk) | 8689 | else if (n < this_chunk) |
| @@ -9081,14 +9105,14 @@ check_windows_init_file (void) | |||
| 9081 | "not unpacked properly.\nSee the README.W32 file in the " | 9105 | "not unpacked properly.\nSee the README.W32 file in the " |
| 9082 | "top-level Emacs directory for more information.", | 9106 | "top-level Emacs directory for more information.", |
| 9083 | init_file_name, load_path); | 9107 | init_file_name, load_path); |
| 9084 | needed = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer, | 9108 | needed = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, |
| 9085 | -1, NULL, 0); | 9109 | buffer, -1, NULL, 0); |
| 9086 | if (needed > 0) | 9110 | if (needed > 0) |
| 9087 | { | 9111 | { |
| 9088 | wchar_t *msg_w = alloca ((needed + 1) * sizeof (wchar_t)); | 9112 | wchar_t *msg_w = alloca ((needed + 1) * sizeof (wchar_t)); |
| 9089 | 9113 | ||
| 9090 | pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, buffer, -1, | 9114 | pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, buffer, |
| 9091 | msg_w, needed); | 9115 | -1, msg_w, needed); |
| 9092 | needed = pWideCharToMultiByte (CP_ACP, 0, msg_w, -1, | 9116 | needed = pWideCharToMultiByte (CP_ACP, 0, msg_w, -1, |
| 9093 | NULL, 0, NULL, NULL); | 9117 | NULL, 0, NULL, NULL); |
| 9094 | if (needed > 0) | 9118 | if (needed > 0) |
| @@ -9275,6 +9299,7 @@ maybe_load_unicows_dll (void) | |||
| 9275 | (MultiByteToWideChar_Proc)GetProcAddress (ret, "MultiByteToWideChar"); | 9299 | (MultiByteToWideChar_Proc)GetProcAddress (ret, "MultiByteToWideChar"); |
| 9276 | pWideCharToMultiByte = | 9300 | pWideCharToMultiByte = |
| 9277 | (WideCharToMultiByte_Proc)GetProcAddress (ret, "WideCharToMultiByte"); | 9301 | (WideCharToMultiByte_Proc)GetProcAddress (ret, "WideCharToMultiByte"); |
| 9302 | multiByteToWideCharFlags = MB_ERR_INVALID_CHARS; | ||
| 9278 | return ret; | 9303 | return ret; |
| 9279 | } | 9304 | } |
| 9280 | else | 9305 | else |
| @@ -9304,6 +9329,11 @@ maybe_load_unicows_dll (void) | |||
| 9304 | pointers; no need for the LoadLibrary dance. */ | 9329 | pointers; no need for the LoadLibrary dance. */ |
| 9305 | pMultiByteToWideChar = MultiByteToWideChar; | 9330 | pMultiByteToWideChar = MultiByteToWideChar; |
| 9306 | pWideCharToMultiByte = WideCharToMultiByte; | 9331 | pWideCharToMultiByte = WideCharToMultiByte; |
| 9332 | /* On NT 4.0, though, MB_ERR_INVALID_CHARS is not supported. */ | ||
| 9333 | if (w32_major_version < 5) | ||
| 9334 | multiByteToWideCharFlags = 0; | ||
| 9335 | else | ||
| 9336 | multiByteToWideCharFlags = MB_ERR_INVALID_CHARS; | ||
| 9307 | return LoadLibrary ("Gdi32.dll"); | 9337 | return LoadLibrary ("Gdi32.dll"); |
| 9308 | } | 9338 | } |
| 9309 | } | 9339 | } |
| @@ -183,6 +183,7 @@ typedef int (WINAPI *MultiByteToWideChar_Proc)(UINT,DWORD,LPCSTR,int,LPWSTR,int) | |||
| 183 | typedef int (WINAPI *WideCharToMultiByte_Proc)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL); | 183 | typedef int (WINAPI *WideCharToMultiByte_Proc)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL); |
| 184 | extern MultiByteToWideChar_Proc pMultiByteToWideChar; | 184 | extern MultiByteToWideChar_Proc pMultiByteToWideChar; |
| 185 | extern WideCharToMultiByte_Proc pWideCharToMultiByte; | 185 | extern WideCharToMultiByte_Proc pWideCharToMultiByte; |
| 186 | extern DWORD multiByteToWideCharFlags; | ||
| 186 | 187 | ||
| 187 | extern void init_environment (char **); | 188 | extern void init_environment (char **); |
| 188 | extern void check_windows_init_file (void); | 189 | extern void check_windows_init_file (void); |
diff --git a/src/w32fns.c b/src/w32fns.c index f3806a992a0..01f5d6f3ae0 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -6984,12 +6984,12 @@ value of DIR as in previous invocations; this is standard Windows behavior. */) | |||
| 6984 | if (errno == ENOENT && filename_buf_w[MAX_PATH - 1] != 0) | 6984 | if (errno == ENOENT && filename_buf_w[MAX_PATH - 1] != 0) |
| 6985 | report_file_error ("filename too long", default_filename); | 6985 | report_file_error ("filename too long", default_filename); |
| 6986 | } | 6986 | } |
| 6987 | len = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, | 6987 | len = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, |
| 6988 | SSDATA (prompt), -1, NULL, 0); | 6988 | SSDATA (prompt), -1, NULL, 0); |
| 6989 | if (len > 32768) | 6989 | if (len > 32768) |
| 6990 | len = 32768; | 6990 | len = 32768; |
| 6991 | prompt_w = alloca (len * sizeof (wchar_t)); | 6991 | prompt_w = alloca (len * sizeof (wchar_t)); |
| 6992 | pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, | 6992 | pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, |
| 6993 | SSDATA (prompt), -1, prompt_w, len); | 6993 | SSDATA (prompt), -1, prompt_w, len); |
| 6994 | } | 6994 | } |
| 6995 | else | 6995 | else |
| @@ -7002,12 +7002,12 @@ value of DIR as in previous invocations; this is standard Windows behavior. */) | |||
| 7002 | if (errno == ENOENT && filename_buf_a[MAX_PATH - 1] != 0) | 7002 | if (errno == ENOENT && filename_buf_a[MAX_PATH - 1] != 0) |
| 7003 | report_file_error ("filename too long", default_filename); | 7003 | report_file_error ("filename too long", default_filename); |
| 7004 | } | 7004 | } |
| 7005 | len = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, | 7005 | len = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, |
| 7006 | SSDATA (prompt), -1, NULL, 0); | 7006 | SSDATA (prompt), -1, NULL, 0); |
| 7007 | if (len > 32768) | 7007 | if (len > 32768) |
| 7008 | len = 32768; | 7008 | len = 32768; |
| 7009 | prompt_w = alloca (len * sizeof (wchar_t)); | 7009 | prompt_w = alloca (len * sizeof (wchar_t)); |
| 7010 | pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, | 7010 | pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, |
| 7011 | SSDATA (prompt), -1, prompt_w, len); | 7011 | SSDATA (prompt), -1, prompt_w, len); |
| 7012 | len = pWideCharToMultiByte (CP_ACP, 0, prompt_w, -1, NULL, 0, NULL, NULL); | 7012 | len = pWideCharToMultiByte (CP_ACP, 0, prompt_w, -1, NULL, 0, NULL, NULL); |
| 7013 | if (len > 32768) | 7013 | if (len > 32768) |
| @@ -7489,10 +7489,10 @@ a ShowWindow flag: | |||
| 7489 | current_dir = ENCODE_FILE (current_dir); | 7489 | current_dir = ENCODE_FILE (current_dir); |
| 7490 | /* Cannot use filename_to_utf16/ansi with DOCUMENT, since it could | 7490 | /* Cannot use filename_to_utf16/ansi with DOCUMENT, since it could |
| 7491 | be a URL that is not limited to MAX_PATH chararcters. */ | 7491 | be a URL that is not limited to MAX_PATH chararcters. */ |
| 7492 | doclen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, | 7492 | doclen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, |
| 7493 | SSDATA (document), -1, NULL, 0); | 7493 | SSDATA (document), -1, NULL, 0); |
| 7494 | doc_w = xmalloc (doclen * sizeof (wchar_t)); | 7494 | doc_w = xmalloc (doclen * sizeof (wchar_t)); |
| 7495 | pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, | 7495 | pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, |
| 7496 | SSDATA (document), -1, doc_w, doclen); | 7496 | SSDATA (document), -1, doc_w, doclen); |
| 7497 | if (use_unicode) | 7497 | if (use_unicode) |
| 7498 | { | 7498 | { |
| @@ -7507,12 +7507,12 @@ a ShowWindow flag: | |||
| 7507 | int len; | 7507 | int len; |
| 7508 | 7508 | ||
| 7509 | parameters = ENCODE_SYSTEM (parameters); | 7509 | parameters = ENCODE_SYSTEM (parameters); |
| 7510 | len = pMultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS, | 7510 | len = pMultiByteToWideChar (CP_ACP, multiByteToWideCharFlags, |
| 7511 | SSDATA (parameters), -1, NULL, 0); | 7511 | SSDATA (parameters), -1, NULL, 0); |
| 7512 | if (len > 32768) | 7512 | if (len > 32768) |
| 7513 | len = 32768; | 7513 | len = 32768; |
| 7514 | params_w = alloca (len * sizeof (wchar_t)); | 7514 | params_w = alloca (len * sizeof (wchar_t)); |
| 7515 | pMultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS, | 7515 | pMultiByteToWideChar (CP_ACP, multiByteToWideCharFlags, |
| 7516 | SSDATA (parameters), -1, params_w, len); | 7516 | SSDATA (parameters), -1, params_w, len); |
| 7517 | params_w[len - 1] = 0; | 7517 | params_w[len - 1] = 0; |
| 7518 | } | 7518 | } |
| @@ -8959,7 +8959,7 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip, | |||
| 8959 | later versions support up to 128. */ | 8959 | later versions support up to 128. */ |
| 8960 | if (nidw.cbSize == MYNOTIFYICONDATAW_V1_SIZE) | 8960 | if (nidw.cbSize == MYNOTIFYICONDATAW_V1_SIZE) |
| 8961 | { | 8961 | { |
| 8962 | tiplen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, | 8962 | tiplen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, |
| 8963 | tip, utf8_mbslen_lim (tip, 63), | 8963 | tip, utf8_mbslen_lim (tip, 63), |
| 8964 | tipw, 64); | 8964 | tipw, 64); |
| 8965 | if (tiplen >= 63) | 8965 | if (tiplen >= 63) |
| @@ -8967,7 +8967,7 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip, | |||
| 8967 | } | 8967 | } |
| 8968 | else | 8968 | else |
| 8969 | { | 8969 | { |
| 8970 | tiplen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, | 8970 | tiplen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, |
| 8971 | tip, utf8_mbslen_lim (tip, 127), | 8971 | tip, utf8_mbslen_lim (tip, 127), |
| 8972 | tipw, 128); | 8972 | tipw, 128); |
| 8973 | if (tiplen >= 127) | 8973 | if (tiplen >= 127) |
| @@ -8986,7 +8986,7 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip, | |||
| 8986 | { | 8986 | { |
| 8987 | int slen; | 8987 | int slen; |
| 8988 | 8988 | ||
| 8989 | slen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, | 8989 | slen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, |
| 8990 | msg, utf8_mbslen_lim (msg, 255), | 8990 | msg, utf8_mbslen_lim (msg, 255), |
| 8991 | msgw, 256); | 8991 | msgw, 256); |
| 8992 | if (slen >= 255) | 8992 | if (slen >= 255) |
| @@ -8999,7 +8999,7 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip, | |||
| 8999 | } | 8999 | } |
| 9000 | wcscpy (nidw.szInfo, msgw); | 9000 | wcscpy (nidw.szInfo, msgw); |
| 9001 | nidw.uTimeout = timeout; | 9001 | nidw.uTimeout = timeout; |
| 9002 | slen = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, | 9002 | slen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, |
| 9003 | title, utf8_mbslen_lim (title, 63), | 9003 | title, utf8_mbslen_lim (title, 63), |
| 9004 | titlew, 64); | 9004 | titlew, 64); |
| 9005 | if (slen >= 63) | 9005 | if (slen >= 63) |
| @@ -9670,6 +9670,12 @@ static PVOID except_addr; | |||
| 9670 | 9670 | ||
| 9671 | /* Stack overflow recovery. */ | 9671 | /* Stack overflow recovery. */ |
| 9672 | 9672 | ||
| 9673 | /* MinGW headers don't declare this (should be in malloc.h). Also, | ||
| 9674 | the function is not present pre-W2K, so make the call through | ||
| 9675 | a function pointer. */ | ||
| 9676 | typedef int (__cdecl *_resetstkoflw_proc) (void); | ||
| 9677 | static _resetstkoflw_proc resetstkoflw; | ||
| 9678 | |||
| 9673 | /* Re-establish the guard page at stack limit. This is needed because | 9679 | /* Re-establish the guard page at stack limit. This is needed because |
| 9674 | when a stack overflow is detected, Windows removes the guard bit | 9680 | when a stack overflow is detected, Windows removes the guard bit |
| 9675 | from the guard page, so if we don't re-establish that protection, | 9681 | from the guard page, so if we don't re-establish that protection, |
| @@ -9677,12 +9683,14 @@ static PVOID except_addr; | |||
| 9677 | void | 9683 | void |
| 9678 | w32_reset_stack_overflow_guard (void) | 9684 | w32_reset_stack_overflow_guard (void) |
| 9679 | { | 9685 | { |
| 9680 | /* MinGW headers don't declare this (should be in malloc.h). */ | 9686 | if (resetstkoflw == NULL) |
| 9681 | _CRTIMP int __cdecl _resetstkoflw (void); | 9687 | resetstkoflw = |
| 9682 | 9688 | (_resetstkoflw_proc)GetProcAddress (GetModuleHandle ("msvcrt.dll"), | |
| 9689 | "_resetstkoflw"); | ||
| 9683 | /* We ignore the return value. If _resetstkoflw fails, the next | 9690 | /* We ignore the return value. If _resetstkoflw fails, the next |
| 9684 | stack overflow will crash the program. */ | 9691 | stack overflow will crash the program. */ |
| 9685 | (void)_resetstkoflw (); | 9692 | if (resetstkoflw != NULL) |
| 9693 | (void)resetstkoflw (); | ||
| 9686 | } | 9694 | } |
| 9687 | 9695 | ||
| 9688 | static void | 9696 | static void |
| @@ -9927,6 +9935,8 @@ globals_of_w32fns (void) | |||
| 9927 | 9935 | ||
| 9928 | after_deadkey = -1; | 9936 | after_deadkey = -1; |
| 9929 | 9937 | ||
| 9938 | resetstkoflw = NULL; | ||
| 9939 | |||
| 9930 | /* MessageBox does not work without this when linked to comctl32.dll 6.0. */ | 9940 | /* MessageBox does not work without this when linked to comctl32.dll 6.0. */ |
| 9931 | InitCommonControls (); | 9941 | InitCommonControls (); |
| 9932 | 9942 | ||
diff --git a/src/w32heap.c b/src/w32heap.c index 54646bfbe3e..3d1c5ff50a2 100644 --- a/src/w32heap.c +++ b/src/w32heap.c | |||
| @@ -258,9 +258,18 @@ init_heap (void) | |||
| 258 | } | 258 | } |
| 259 | #endif | 259 | #endif |
| 260 | 260 | ||
| 261 | the_malloc_fn = malloc_after_dump; | 261 | if (os_subtype == OS_9X) |
| 262 | the_realloc_fn = realloc_after_dump; | 262 | { |
| 263 | the_free_fn = free_after_dump; | 263 | the_malloc_fn = malloc_after_dump_9x; |
| 264 | the_realloc_fn = realloc_after_dump_9x; | ||
| 265 | the_free_fn = free_after_dump_9x; | ||
| 266 | } | ||
| 267 | else | ||
| 268 | { | ||
| 269 | the_malloc_fn = malloc_after_dump; | ||
| 270 | the_realloc_fn = realloc_after_dump; | ||
| 271 | the_free_fn = free_after_dump; | ||
| 272 | } | ||
| 264 | } | 273 | } |
| 265 | else | 274 | else |
| 266 | { | 275 | { |
| @@ -291,9 +300,18 @@ init_heap (void) | |||
| 291 | exit (-1); | 300 | exit (-1); |
| 292 | } | 301 | } |
| 293 | heap = s_pfn_Rtl_Create_Heap (0, data_region_base, 0, 0, NULL, ¶ms); | 302 | heap = s_pfn_Rtl_Create_Heap (0, data_region_base, 0, 0, NULL, ¶ms); |
| 294 | the_malloc_fn = malloc_before_dump; | 303 | |
| 295 | the_realloc_fn = realloc_before_dump; | 304 | if (os_subtype == OS_9X) |
| 296 | the_free_fn = free_before_dump; | 305 | { |
| 306 | fprintf (stderr, "Cannot dump Emacs on Windows 9X; exiting.\n"); | ||
| 307 | exit (-1); | ||
| 308 | } | ||
| 309 | else | ||
| 310 | { | ||
| 311 | the_malloc_fn = malloc_before_dump; | ||
| 312 | the_realloc_fn = realloc_before_dump; | ||
| 313 | the_free_fn = free_before_dump; | ||
| 314 | } | ||
| 297 | } | 315 | } |
| 298 | 316 | ||
| 299 | /* Update system version information to match current system. */ | 317 | /* Update system version information to match current system. */ |
| @@ -504,6 +522,65 @@ free_before_dump (void *ptr) | |||
| 504 | } | 522 | } |
| 505 | } | 523 | } |
| 506 | 524 | ||
| 525 | /* On Windows 9X, HeapAlloc may return pointers that are not aligned | ||
| 526 | on 8-byte boundary, alignment which is required by the Lisp memory | ||
| 527 | management. To circumvent this problem, manually enforce alignment | ||
| 528 | on Windows 9X. */ | ||
| 529 | |||
| 530 | void * | ||
| 531 | malloc_after_dump_9x (size_t size) | ||
| 532 | { | ||
| 533 | void *p = malloc_after_dump (size + 8); | ||
| 534 | void *pa; | ||
| 535 | if (p == NULL) | ||
| 536 | return p; | ||
| 537 | pa = (void*)(((intptr_t)p + 8) & ~7); | ||
| 538 | *((void**)pa-1) = p; | ||
| 539 | return pa; | ||
| 540 | } | ||
| 541 | |||
| 542 | void * | ||
| 543 | realloc_after_dump_9x (void *ptr, size_t size) | ||
| 544 | { | ||
| 545 | if (FREEABLE_P (ptr)) | ||
| 546 | { | ||
| 547 | void *po = *((void**)ptr-1); | ||
| 548 | void *p; | ||
| 549 | void *pa; | ||
| 550 | p = realloc_after_dump (po, size + 8); | ||
| 551 | if (p == NULL) | ||
| 552 | return p; | ||
| 553 | pa = (void*)(((intptr_t)p + 8) & ~7); | ||
| 554 | if (ptr != NULL && | ||
| 555 | (char*)pa - (char*)p != (char*)ptr - (char*)po) | ||
| 556 | { | ||
| 557 | /* Handle the case where alignment in pre-realloc and | ||
| 558 | post-realloc blocks does not match. */ | ||
| 559 | MoveMemory (pa, (void*)((char*)p + ((char*)ptr - (char*)po)), size); | ||
| 560 | } | ||
| 561 | *((void**)pa-1) = p; | ||
| 562 | return pa; | ||
| 563 | } | ||
| 564 | else | ||
| 565 | { | ||
| 566 | /* Non-freeable pointers have no alignment-enforcing header | ||
| 567 | (since dumping is not allowed on Windows 9X). */ | ||
| 568 | void* p = malloc_after_dump_9x (size); | ||
| 569 | if (p != NULL) | ||
| 570 | CopyMemory (p, ptr, size); | ||
| 571 | return p; | ||
| 572 | } | ||
| 573 | } | ||
| 574 | |||
| 575 | void | ||
| 576 | free_after_dump_9x (void *ptr) | ||
| 577 | { | ||
| 578 | if (FREEABLE_P (ptr)) | ||
| 579 | { | ||
| 580 | free_after_dump (*((void**)ptr-1)); | ||
| 581 | } | ||
| 582 | } | ||
| 583 | |||
| 507 | #ifdef ENABLE_CHECKING | 584 | #ifdef ENABLE_CHECKING |
| 508 | void | 585 | void |
| 509 | report_temacs_memory_usage (void) | 586 | report_temacs_memory_usage (void) |
diff --git a/src/w32proc.c b/src/w32proc.c index a65f085fb3d..a89a9850466 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -3702,6 +3702,13 @@ of time slices to wait (effectively boosting the priority of the child | |||
| 3702 | process temporarily). A value of zero disables waiting entirely. */); | 3702 | process temporarily). A value of zero disables waiting entirely. */); |
| 3703 | w32_pipe_read_delay = 50; | 3703 | w32_pipe_read_delay = 50; |
| 3704 | 3704 | ||
| 3705 | DEFVAR_INT ("w32-pipe-buffer-size", w32_pipe_buffer_size, | ||
| 3706 | doc: /* Size of buffer for pipes created to communicate with subprocesses. | ||
| 3707 | The size is in bytes, and must be non-negative. The default is zero, | ||
| 3708 | which lets the OS use its default size, usually 4KB (4096 bytes). | ||
| 3709 | Any negative value means to use the default value of zero. */); | ||
| 3710 | w32_pipe_buffer_size = 0; | ||
| 3711 | |||
| 3705 | DEFVAR_LISP ("w32-downcase-file-names", Vw32_downcase_file_names, | 3712 | DEFVAR_LISP ("w32-downcase-file-names", Vw32_downcase_file_names, |
| 3706 | doc: /* Non-nil means convert all-upper case file names to lower case. | 3713 | doc: /* Non-nil means convert all-upper case file names to lower case. |
| 3707 | This applies when performing completions and file name expansion. | 3714 | This applies when performing completions and file name expansion. |
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); |