aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoakim Verona2013-07-14 11:04:49 +0200
committerJoakim Verona2013-07-14 11:04:49 +0200
commit0bb9bb0841d89fff09820a57369df4cb01b16b43 (patch)
tree832bf9fa8415eef0ce464d22b3ee1300cfa90bb1 /src
parent3718127221fbbc31f8ebd027ab7c95403dbe9118 (diff)
parent3af1c8684ed6e48fbc21481d129e9aa164752c6e (diff)
downloademacs-0bb9bb0841d89fff09820a57369df4cb01b16b43.tar.gz
emacs-0bb9bb0841d89fff09820a57369df4cb01b16b43.zip
Merge branch 'trunk' into xwidget
Conflicts: src/xdisp.c
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog475
-rw-r--r--src/alloc.c6
-rw-r--r--src/atimer.c2
-rw-r--r--src/buffer.c10
-rw-r--r--src/bytecode.c7
-rw-r--r--src/callproc.c159
-rw-r--r--src/coding.c2
-rw-r--r--src/cygw32.c2
-rw-r--r--src/data.c3
-rw-r--r--src/dbusbind.c8
-rw-r--r--src/deps.mk2
-rw-r--r--src/dired.c2
-rw-r--r--src/dispextern.h8
-rw-r--r--src/dispnew.c22
-rw-r--r--src/emacs.c100
-rw-r--r--src/eval.c71
-rw-r--r--src/fileio.c153
-rw-r--r--src/filelock.c20
-rw-r--r--src/fns.c26
-rw-r--r--src/frame.c11
-rw-r--r--src/gfilenotify.c14
-rw-r--r--src/gnutls.h2
-rw-r--r--src/image.c104
-rw-r--r--src/inotify.c61
-rw-r--r--src/keyboard.c7
-rw-r--r--src/lisp.h26
-rw-r--r--src/lread.c101
-rw-r--r--src/makefile.w32-in2
-rw-r--r--src/nsfns.m127
-rw-r--r--src/nsfont.m1
-rw-r--r--src/nsmenu.m6
-rw-r--r--src/nsterm.h6
-rw-r--r--src/nsterm.m33
-rw-r--r--src/print.c17
-rw-r--r--src/process.c159
-rw-r--r--src/process.h8
-rw-r--r--src/profiler.c12
-rw-r--r--src/ralloc.c2
-rw-r--r--src/regex.c33
-rw-r--r--src/regex.h46
-rw-r--r--src/search.c2
-rw-r--r--src/sheap.c4
-rw-r--r--src/sound.c2
-rw-r--r--src/syntax.c272
-rw-r--r--src/syntax.h296
-rw-r--r--src/sysdep.c263
-rw-r--r--src/sysstdio.h2
-rw-r--r--src/systime.h23
-rw-r--r--src/term.c53
-rw-r--r--src/termcap.c114
-rw-r--r--src/termhooks.h2
-rw-r--r--src/terminal.c4
-rw-r--r--src/undo.c7
-rw-r--r--src/unexaix.c26
-rw-r--r--src/unexcoff.c22
-rw-r--r--src/unexcw.c10
-rw-r--r--src/unexelf.c17
-rw-r--r--src/unexhp9k800.c9
-rw-r--r--src/unexmacosx.c9
-rw-r--r--src/w32.c15
-rw-r--r--src/w32.h2
-rw-r--r--src/w32fns.c281
-rw-r--r--src/w32term.c34
-rw-r--r--src/window.c12
-rw-r--r--src/xdisp.c130
-rw-r--r--src/xfaces.c5
-rw-r--r--src/xrdb.c5
-rw-r--r--src/xsettings.c6
-rw-r--r--src/xterm.c126
-rw-r--r--src/xterm.h2
70 files changed, 2286 insertions, 1325 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 322b8271f14..6ee0cacb520 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,476 @@
12013-07-14 Paul Eggert <eggert@cs.ucla.edu>
2
3 * callproc.c (child_setup, relocate_fd) [!DOS_NT]:
4 * process.c (create_process) [!DOS_NT]:
5 Remove now-unnecessary calls to emacs_close.
6
72013-07-13 Eli Zaretskii <eliz@gnu.org>
8
9 * w32term.c (x_draw_hollow_cursor): Delete the brush object when
10 returning early. (Bug#14850)
11
12 * coding.c (syms_of_coding): Set up inhibit-null-byte-detection
13 and inhibit-iso-escape-detection attributes of 'undecided'.
14 (Bug#14822)
15
162013-07-13 Paul Eggert <eggert@cs.ucla.edu>
17
18 * deps.mk (sysdep.o): Remove dependency on ../lib/ignore-value.h.
19 Reported by Herbert J. Skuhra in
20 <http://lists.gnu.org/archive/html/emacs-devel/2013-07/msg00455.html>.
21
22 Don't lose top specpdl entry when memory is exhausted.
23 * eval.c (grow_specpdl): Increment specpdl top by 1 and check for
24 specpdl overflow here, to simplify callers; all callers changed.
25 Always reserve an unused entry at the stack top; this avoids
26 losing the top entry's information when memory is exhausted.
27
282013-07-12 Paul Eggert <eggert@cs.ucla.edu>
29
30 Clean up errno reporting and fix some errno-reporting bugs.
31 * callproc.c (Fcall_process):
32 * fileio.c (Fcopy_file, Finsert_file_contents, Fwrite_region):
33 * process.c (create_process, Fmake_network_process):
34 * unexaix.c (report_error):
35 * unexcoff.c (report_error):
36 Be more careful about reporting the errno of failed operations.
37 The code previously reported the wrong errno sometimes.
38 Also, prefer report_file_errno to setting errno + report_file_error.
39 (Fcall_process): Look at openp return value rather than at path,
40 as that's a bit faster and clearer when there's a numeric predicate.
41 * fileio.c (report_file_errno): New function, with most of the
42 old contents of report_file_error.
43 (report_file_error): Use it.
44 (Ffile_exists_p, Ffile_accessible_directory_p):
45 Set errno to 0 when it is junk.
46 * fileio.c (Faccess_file):
47 * image.c (x_create_bitmap_from_file):
48 Use faccessat rather than opening the file, to avoid the hassle of
49 having a file descriptor open.
50 * lisp.h (report_file_errno): New decl.
51 * lread.c (Flocate_file_internal): File descriptor 0 is valid, too.
52
53 Minor EBADF fixes.
54 * process.c (create_process, wait_reading_process_output) [AIX]:
55 Remove obsolete SIGHUP-related code, as Emacs no longer disables
56 SIGHUP, so EBADF is no longer acceptable here (it wouldn't work in
57 a multithreaded environment anyway).
58 * sysdep.c (emacs_close): It's not dangerous to invoke emacs_close (-1).
59
602013-07-12 Andreas Schwab <schwab@linux-m68k.org>
61
62 * image.c (x_find_image_file): Don't close a remote file handle.
63
642013-07-12 Paul Eggert <eggert@cs.ucla.edu>
65
66 Fix races with threads and file descriptors.
67 * callproc.c (Fcall_process_region):
68 * dired.c (open_directory):
69 * emacs.c (main, Fdaemon_initialized):
70 * image.c (x_find_image_file):
71 * inotify.c (Finotify_rm_watch):
72 * lread.c (Flocate_file_internal):
73 * process.c (Fnetwork_interface_list, Fnetwork_interface_info):
74 * term.c (term_mouse_moveto, init_tty):
75 * termcap.c (tgetent):
76 * unexaix.c, unexcoff.c (report_error, report_error_1, adjust_lnnoptrs)
77 * unexaix.c, unexcoff.c, unexcw.c, unexelf.c (unexec):
78 * unexhp9k800.c, unexmacosx.c (unexec):
79 * callproc.c (Fcall_process_region):
80 Use emacs_close, not close.
81 * sysdep.c (POSIX_CLOSE_RESTART, posix_close) [!POSIX_CLOSE_RESTART]:
82 New macro and function, which emulates the POSIX_CLOSE_RESTART macro
83 and posix_close function on current platforms (which all lack them).
84 (emacs_close): Use it. This should fix the races on GNU/Linux and
85 on AIX and on future platforms that support POSIX_CLOSE_RESTART,
86 and it should avoid closing random victim file descriptors on
87 other platforms.
88
892013-07-11 Paul Eggert <eggert@cs.ucla.edu>
90
91 * inotify.c (uninitialized): Remove. All uses replaced by -1.
92 (Finotify_add_watch): Simplify, since -1 means uninitialized now.
93 Touch up doc a bit.
94
95 * eval.c (backtrace_function, backtrace_args): Now EXTERNALLY_VISIBLE.
96 This is for .gdbinit xbacktrace.
97
98 * sysdep.c, term.c, termcap.c, terminal.c: Integer-related minor fixes.
99 * sysdep.c (emacs_get_tty): Return void, since nobody uses the value.
100 (emacs_set_tty): Now static.
101 * sysdep.c (emacs_set_tty, tabs_safe_p, emacs_close):
102 * term.c (tty_capable_p, tty_default_color_capabilities)
103 (get_tty_terminal, term_mouse_movement)
104 (handle_one_term_event, init_tty, maybe_fatal):
105 * termcap.c (tgetst1, struct termcap_buffer, valid_filename_p)
106 (tgetent, scan_file, name_match, compare_contin):
107 * terminal.c (get_terminal):
108 Use bool for boolean.
109 * sysdep.c (init_system_name): Don't overflow stack on huge hostname.
110 Prefer char to unsigned char if either will do.
111 * term.c (OUTPUT, turn_on_face): Omit unnecessary casts to int.
112 (tty_write_glyphs): Prefer int to unsigned.
113 (produce_glyphless_glyph): Remove 2nd (unused) int arg.
114 All callers changed.
115 * termcap.c (tprint, main) [TEST]: Remove non-working test.
116
1172013-07-10 Paul Eggert <eggert@cs.ucla.edu>
118
119 Port to C89.
120 * bytecode.c (BYTE_CODE_THREADED): Do not define if __STRICT_ANSI__.
121 (B__dummy__): New dummy symbol, to pacify C89.
122 * dbusbind.c (XD_DEBUG_MESSAGE): Omit debugging on C89 hosts, since
123 they can't grok varargs macros.
124 * dispnew.c (add_window_display_history)
125 (add_frame_display_history):
126 * print.c (print_object):
127 * xdisp.c (debug_method_add):
128 Use %p printf format only for void pointers.
129 * emacs.c (usage_message): New constant, replacing ...
130 (USAGE1, USAGE2, USAGE3): Remove; they were too long for C89.
131 (main): Adjust to usage reorg.
132 * fns.c (syms_of_fns):
133 * profiler.c (syms_of_profiler):
134 Don't use non-constant struct initializers.
135 * gnutls.h (gnutls_initstage_t):
136 * lisp.h (enum Lisp_Fwd_Type):
137 * lread.c (lisp_file_lexically_bound_p):
138 * xsettings.c (anonymous enum):
139 Remove trailing comma.
140 * xsettings.c (apply_xft_settings): Use %f, not %lf; %lf is a C99ism.
141 * lisp.h (ENUM_BF): Use unsigned if pedantic.
142 (DEFUN_FUNCTION_INIT): New macro, that falls back on a cast if pre-C99.
143 (DEFUN): Use it.
144 * regex.c (const_re_char): New type, to pacify strict C89.
145 All uses of 'const re_char' replaced to use it.
146 * regex.h (_Restrict_): Rename from __restrict, to avoid clash
147 with glibc when strict C89. This change is imported from gnulib.
148 All uses changed.
149 (_Restrict_arr_): Rename from __restrict_arr, similarly.
150 * sysdep.c (time_from_jiffies) [!HAVE_LONG_LONG_INT]:
151 Omit GNU_LINUX implementation, since it requires long long.
152 * xterm.c (x_draw_underwave):
153 Do not assume the traditional order of struct's members.
154 (x_term_init): Rewrite to avoid the need for non-constant structure
155 initializers.
156
157 Syntax cleanup, mostly replacing macros with functions.
158` This removes the need for the syntax_temp hack.
159 * search.c: Include syntax.h after buffer.h, since syntax.h uses BVAR.
160 * syntax.c (SYNTAX_INLINE): New macro.
161 (SYNTAX_FLAGS_COMSTART_FIRST, SYNTAX_FLAGS_COMSTART_SECOND)
162 (SYNTAX_FLAGS_COMEND_FIRST, SYNTAX_FLAGS_COMEND_SECOND)
163 (SYNTAX_FLAGS_PREFIX, SYNTAX_FLAGS_COMMENT_STYLEB)
164 (SYNTAX_FLAGS_COMMENT_STYLEC, SYNTAX_FLAGS_COMMENT_STYLEC2)
165 (SYNTAX_FLAGS_COMMENT_NESTED, SYNTAX_FLAGS_COMMENT_STYLE)
166 (SYNTAX_COMEND_FIRST): Now functions, not macros.
167 (ST_COMMENT_STYLE, ST_STRING_STYLE, INTERVALS_AT_ONCE):
168 Now constants, not macros.
169 (syntax_temp) [!__GNUC__]: Remove.
170 (SYNTAX_PREFIX): Remove; all uses replaced by syntax_prefix_flag_p.
171 (syntax_prefix_flag_p): Move implementation of SYNTAX_PREFIX here.
172 (SET_RAW_SYNTAX_ENTRY, SET_RAW_SYNTAX_ENTRY_RANGE, SYNTAX_MATCH)
173 (SETUP_SYNTAX_TABLE, SETUP_SYNTAX_TABLE_FOR_OBJECT):
174 Move here from syntax.h; now functions, not macros. Except for the
175 last function, these are static since only syntax.c uses them.
176 (syntax_multibyte): Rename from SYNTAX_WITH_MULTIBYTE_CHECK.
177 All uses changed. Now a function, not a macro; use this fact
178 to simplify the code.
179 (scan_lists, scan_sexps_forward): Remove workarounds for ancient
180 compiler bugs; no longer relevant.
181 * syntax.h: Use INLINE_HEADER_BEGIN, INLINE_HEADER_END.
182 (SYNTAX_INLINE): New macro.
183 (struct gl_state_s, gl_state): Move earlier, so that it's in scope
184 for the new functions. Use bool for boolean member.
185 (SYNTAX_ENTRY, SYNTAX, SYNTAX_WITH_FLAGS, SYNTAX_MATCH)
186 (SYNTAX_TABLE_BYTE_TO_CHAR, UPDATE_SYNTAX_TABLE_FORWARD)
187 (UPDATE_SYNTAX_TABLE_BACKWARD, UPDATE_SYNTAX_TABLE)
188 (SETUP_BUFFER_SYNTAX_TABLE):
189 Now extern inline functions, not macros.
190 (CURRENT_SYNTAX_TABLE, SYNTAX_ENTRY_INT):
191 Remove; all uses replaced by implementation.
192 (syntax_temp) [!__GNUC__]: Remove decl.
193 (SETUP_SYNTAX_TABLE_FOR_OBJECT): New decl.
194
1952013-07-10 Jan Djärv <jan.h.d@swipnet.se>
196
197 * emacs.c (main): Fix syntax error.
198
1992013-07-10 Paul Eggert <eggert@cs.ucla.edu>
200
201 Timestamp fixes for undo (Bug#14824).
202 * atimer.c (schedule_atimer):
203 * fileio.c (Ffile_newer_than_file_p):
204 Minor cleanup: use EMACS_TIME_LT so that we can remove EMACS_TIME_GT.
205 * buffer.c (buffer-undo-list): Document (t . 0) and (t . -1).
206 * fileio.c (Fclear_visited_file_modtime): Move to lisp/files.el.
207 (syms_of_fileio): Remove Sclear_visited_file_name.
208 (Fvisited_file_modtime): Return -1, not (-1 ...), when the visited
209 file doesn't exist; this avoids an ambiguity with negative timestamps.
210 (Fset_visited_file_modtime): Accept -1 and 0 as time-list arg.
211 * systime.h (make_emacs_time, invalid_emacs_time):
212 Don't assume struct timespec layout; POSIX doesn't guarantee it.
213 (EMACS_TIME_NE, EMACS_TIME_GT, EMACS_TIME_GE): Remove.
214 * undo.c (record_first_change): Push (visited-file-modtime) onto
215 undo list rather than reimplementing it by hand, incorrectly.
216
2172013-07-09 Ken Brown <kbrown@cornell.edu>
218
219 * sheap.c (STATIC_HEAP_SIZE) [__x86_64__]: Increase to 18MB.
220
2212013-07-09 Juanma Barranquero <lekktu@gmail.com>
222
223 * makefile.w32-in ($(BLD)/emacs.$(O), $(BLD)/sysdep.$(O)): Update.
224
2252013-07-09 Paul Eggert <eggert@cs.ucla.edu>
226
227 Handle errno and exit status a bit more carefully.
228 * callproc.c (child_setup) [!DOS_NT]: Don't try to stuff an error
229 number into an exit status. Instead, use EXIT_CANCELED.
230 (child_setup) [!MSDOS]: Avoid possible deadlock with vfork.
231 * callproc.c (relocate_fd):
232 * emacs.c (close_output_streams, main):
233 * process.c (create_process):
234 * sysdep.c (sys_subshell) [!DOS_NT || !WINDOWSNT]:
235 Use emacs_perror for simplicity.
236 * callproc.c (relocate_fd, main):
237 * sysdep.c (sys_subshell):
238 Exit with EXIT_CANCELED etc., not 1, when exec setup fails.
239 (shut_down_emacs): Use emacs_write, not write.
240 * emacs.c, sysdep.c: Don't include <ignore-value.h>.
241 * fileio.c (Fcopy_file, e_write):
242 * nsterm.m (ns_select):
243 * process.c (send_process):
244 * sound.c (vox_write):
245 Use emacs_write_sig, not emacs_write.
246 * lisp.h (emacs_write_sig, emacs_perror): New decls.
247 * process.h (EXIT_CANCELED), EXIT_CANNOT_INVOKE, EXIT_ENOENT):
248 New constants.
249 * sysdep.c (emacs_backtrace): Use emacs_write, not ignore_value
250 of write.
251 (emacs_full_write): New function.
252 (emacs_write): Rewrite to use it.
253 (emacswrite_sig, emacs_perror): New functions.
254 * xrdb.c (fatal): Don't invoke perror, since errno might be garbage.
255
2562013-07-08 Magnus Henoch <magnus.henoch@gmail.com> (tiny change).
257
258 * image.c (imagemagick_load_image): Do not use MagickExportImagePixels
259 on NS even if it is present. Pixmap on NS is a void*.
260
2612013-07-07 Paul Eggert <eggert@cs.ucla.edu>
262
263 Port to Ubuntu 10 (Bug#14803).
264 Problem reported by T.V. Raman.
265 * process.c (close_on_exec, accept4, process_socket):
266 Define these if !HAVE_ACCEPT4, not if !SOCK_CLOEXEC.
267
2682013-07-07 Eli Zaretskii <eliz@gnu.org>
269
270 * w32.c (sys_dup): Declare prototype.
271
272 * filelock.c:
273 * emacs.c:
274 * callproc.c [WINDOWSNT]: Include sys/socket.h.
275
2762013-07-07 Paul Eggert <eggert@cs.ucla.edu>
277
278 Make file descriptors close-on-exec when possible (Bug#14803).
279 This simplifies Emacs a bit, since it no longer needs to worry
280 about closing file descriptors by hand in some cases.
281 It also fixes some unlikely races. Not all such races, as
282 libraries often open files internally without setting
283 close-on-exec, but it's an improvement.
284 * alloc.c (valid_pointer_p) [!WINDOWSNT]:
285 * callproc.c (Fcall_process) [!MSDOS]:
286 * emacs.c (main) [!DOS_NT]:
287 * nsterm.m (ns_term_init):
288 * process.c (create_process):
289 Use 'pipe2' with O_CLOEXEC instead of 'pipe'.
290 * emacs.c (Fcall_process_region) [HAVE_MKOSTEMP]:
291 * filelock.c (create_lock_file) [HAVE_MKOSTEMP]:
292 Prefer mkostemp with O_CLOEXEC to mkstemp.
293 * callproc.c (relocate_fd) [!WINDOWSNT]:
294 * emacs.c (main): Use F_DUPFD_CLOEXEC, not plain F_DUPFD.
295 No need to use fcntl (..., F_SETFD, FD_CLOEXEC), since we're
296 now using pipe2.
297 * filelock.c (create_lock_file) [! HAVE_MKOSTEMP]:
298 Make the resulting file descriptor close-on-exec.
299 * lisp.h, lread.c, process.c (close_load_descs, close_process_descs):
300 * lread.c (load_descriptor_list, load_descriptor_unwind):
301 Remove; no longer needed. All uses removed.
302 * process.c (SOCK_CLOEXEC): Define to 0 if not supplied by system.
303 (close_on_exec, accept4, process_socket) [!SOCK_CLOEXEC]:
304 New functions.
305 (socket) [!SOCK_CLOEXEC]: Supply a substitute.
306 (Fmake_network_process, Fnetwork_interface_list):
307 (Fnetwork_interface_info, server_accept_connection):
308 Make newly-created socket close-on-exec.
309 * sysdep.c (emacs_open, emacs_fopen):
310 Make new-created descriptor close-on-exec.
311 * w32.c (fcntl): Support F_DUPFD_CLOEXEC well enough for Emacs.
312 * w32.c, w32.h (pipe2): Rename from 'pipe', with new flags arg.
313
3142013-07-07 Jan Djärv <jan.h.d@swipnet.se>
315
316 * nsterm.m (sendEvent:): Propagate keyboard events to modal windows
317 for NS_IMPL_GNUSTEP.
318
3192013-07-07 Paul Eggert <eggert@cs.ucla.edu>
320
321 Fix openp errno handling.
322 * callproc.c (Fcall_process): Preserve openp errno around close.
323 * lread.c (openp): Set errno when returning -1, as some callers
324 expect this.
325
3262013-07-06 Jan Djärv <jan.h.d@swipnet.se>
327
328 * nsterm.m (sendEvent:): Handle NSAPP_DATA2_RUNFILEDIALOG.
329
330 * nsterm.h (NSSavePanel): Update comment.
331 (NSAPP_DATA2_RUNFILEDIALOG): Define.
332 (ns_run_file_dialog): Declare.
333
334 * nsfns.m: Remove panelOK.
335 (ns_fd_data): New.
336 (ns_run_file_dialog): New function.
337 (Fns_read_file_name): Fill in ns_fd_data, post an event and start the
338 event loop, so file dialog is popped up by ns_run_file_dialog, called
339 by sendEvent (Bug#14578).
340 (EmacsSavePanel, EmacsOpenPanel): Remove ok and cancel methods.
341
3422013-07-06 Eli Zaretskii <eliz@gnu.org>
343
344 * xdisp.c (default_line_pixel_height): New function.
345 (pos_visible_p, move_it_vertically_backward, try_scrolling)
346 (try_cursor_movement, redisplay_window, try_window)
347 (try_window_id): Use it instead of FRAME_LINE_HEIGHT. (Bug#14771)
348
349 * window.c (window_scroll_pixel_based): use
350 default_line_pixel_height.
351
352 * dispextern.h (default_line_pixel_height): Add prototype.
353
354 * frame.c (x_set_line_spacing): Accept a float value for
355 line-spacing parameter, per the documentation.
356
357 * data.c (Fmultibyte_string_p): Doc fix.
358
3592013-07-05 Paul Eggert <eggert@cs.ucla.edu>
360
361 Use emacs_open more consistently when opening files.
362 This handles EINTR more consistently now, and makes it easier
363 to introduce other uniform changes to file descriptor handling.
364 * src/systdio.h: New file.
365 * src/buffer.c (mmap_init):
366 * cygw32.c (chdir_to_default_directory):
367 * dispnew.c (Fopen_termscript):
368 * emacs.c (Fdaemon_initialized):
369 * fileio.c (Fdo_auto_save):
370 * image.c (slurp_file, png_load_body, jpeg_load_body):
371 * keyboard.c (Fopen_dribble_file):
372 * lread.c (Fload):
373 * print.c (Fredirect_debugging_output):
374 * sysdep.c (get_up_time, procfs_ttyname, procfs_get_total_memory):
375 * termcap.c (tgetent):
376 * unexaix.c, unexcoff.c (unexec, adjust_lnnoptrs):
377 * unexcw.c, unexelf.c, unexhp9k800.c, unexmacosx.c (unexec):
378 * w32term.c (w32_initialize) [CYGWIN]:
379 * xfaces.c (Fx_load_color_file):
380 Use emacs_open instead of plain open, and emacs_fopen instead of
381 plain fopen.
382 * dispnew.c, fileio.c, image.c, keyboard.c, lread.c, print.c, sysdep.c:
383 * xfaces.c: Include sysstdio.h rather than stdio.h, for emacs_fopen.
384 * callproc.c (default_output_mode): New constant.
385 (Fcall_process): Use it to call emacs_open instead of plain creat.
386 * dispnew.c (Fopen_termscript): Fix minor race in opening termscript.
387 * sysdep.c (emacs_open): Add commentary and don't call file name "path".
388 (emacs_fopen): New function.
389 * unexaix.c, unexcoff.c, unexelf.c, unexhp9k800.c, unexmacosx.c:
390 Include <lisp.h>, for emacs_open.
391 * unexelf.c (fatal): Remove decl; not needed with <lisp.h> included.
392
393 Remove duplicate #include directives.
394 * alloc.c [GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES]:
395 * xfaces.c:
396 Don't include stdio.h twice.
397 * buffer.c [USE_MMAP_FOR_BUFFERS]:
398 Don't include sys/types.h or stdio.h twice.
399 * fileio.c [WINDOWSNT | MSDOS]: Don't include fcntl.h twice.
400 * lread.c: Don't include coding.h twice.
401 * nsfont.m: Don't include frame.h twice.
402 * process.c [HAVE_RES_INIT]: Don't include <netinet/in.h> twice.
403 * ralloc.c: Don't include <unistd.h> twice.
404 * xdisp.c: Don't include font.h twice.
405 * xterm.c: Don't include fontset.h twice.
406 * xterm.h [USE_X_TOOLKIT]: Don't include X11/StringDefs.h twice.
407
4082013-07-04 Paul Eggert <eggert@cs.ucla.edu>
409
410 Scale ImageMagick images more carefully.
411 * image.c (scale_image_size) [HAVE_IMAGEMAGICK]: New function.
412 (compute_image_size): Use it. Define only if HAVE_IMAGEMAGICK.
413 Be more careful about avoiding undefined behavior after
414 integer overflow and division by zero.
415
4162013-07-04 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
417
418 * w32fns.c (Qgeometry, Qworkarea, Qmm_size, Qframes): New variables.
419 (syms_of_w32fns): DEFSYM them.
420 (MONITORINFOF_PRIMARY, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN)
421 (CCHDEVICENAME): Define macros if not defined.
422 (struct MONITOR_INFO_EX): New struct.
423 (MonitorEnum_Proc, EnumDisplayMonitors_Proc): New prototypes.
424 (enum_display_monitors_fn): New variable.
425 (globals_of_w32fns): Initialize it.
426 (Fx_display_pixel_width, Fx_display_pixel_height)
427 (Fx_display_mm_height, Fx_display_mm_width): Mention behavior on
428 multi-monitor setups in docstrings.
429 (Fx_display_mm_height, Fx_display_mm_width): Approximate whole
430 screen size by primary monitor's millimeter per pixel.
431 (w32_monitor_enum, w32_display_monitor_attributes_list)
432 (w32_display_monitor_attributes_list_fallback)
433 (Fw32_display_monitor_attributes_list): New functions.
434 (syms_of_w32fns): Defsubr Sw32_display_monitor_attributes_list.
435
436 * w32term.c (SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN): Define macros
437 if not defined.
438 (x_display_pixel_height, x_display_pixel_width): Use GetSystemMetrics.
439
4402013-07-04 Michael Albinus <michael.albinus@gmx.de>
441
442 * fileio.c (Qfile_notify_error): New error symbol.
443
444 * gfilenotify.c (Fgfile_add_watch, Fgfile_rm_watch):
445 * inotify.c (inotify_callback, symbol_to_inotifymask)
446 (Finotify_add_watch, Finotify_rm_watch): Use it.
447 (inotifyevent_to_event): Exchange order of cookie and file name.
448 (Finotify_add_watch): Adapt docstring.
449
450 * lisp.h (Qfile_notify_error): Declare.
451
4522013-07-04 Paul Eggert <eggert@cs.ucla.edu>
453
454 Try again to fix FreeBSD bug re multithreaded memory alloc (Bug#14569).
455 * emacs.c (main) [HAVE_PTHREAD && !SYSTEM_MALLOC && !DOUG_LEA_MALLOC]:
456 Do not clear _malloc_thread_enabled_p, undoing the previous change,
457 which did not work (see <http://bugs.gnu.org/14569#307>).
458 (main): Do not invoke malloc_enable_thread if (! CANNOT_DUMP
459 && (!noninteractive || initialized)). This attempts to thread
460 the needle between the Scylla of FreeBSD and the Charybdis of Cygwin.
461
4622013-07-04 Juanma Barranquero <lekktu@gmail.com>
463
464 * image.c (x_to_xcolors) [HAVE_NTGUI]: Remove unused var `hdc'.
465 (x_build_heuristic_mask) [HAVE_NTGUI]: Remove unused var `frame_dc'.
466
4672013-07-04 Paul Eggert <eggert@cs.ucla.edu>
468
469 Try to fix FreeBSD bug re multithreaded memory allocation (Bug#14569).
470 * emacs.c (main) [HAVE_PTHREAD && !SYSTEM_MALLOC && !DOUG_LEA_MALLOC]:
471 Clear _malloc_thread_enabled_p at startup. Reported by Ashish SHUKLA in
472 <http://lists.gnu.org/archive/html/emacs-devel/2013-07/msg00088.html>.
473
12013-07-02 Paul Eggert <eggert@cs.ucla.edu> 4742013-07-02 Paul Eggert <eggert@cs.ucla.edu>
2 475
3 * sysdep.c (sys_siglist) [HAVE_DECL___SYS_SIGLIST]: 476 * sysdep.c (sys_siglist) [HAVE_DECL___SYS_SIGLIST]:
@@ -507,7 +980,7 @@
507 (VALMASK): Also a constant, for benefit of old GDB. 980 (VALMASK): Also a constant, for benefit of old GDB.
508 (LISP_INT_TAG_P): Remove; no longer needed as the only caller 981 (LISP_INT_TAG_P): Remove; no longer needed as the only caller
509 is INTEGERP, which can fold it in. 982 is INTEGERP, which can fold it in.
510 (XLI, XIL, XHASH, XTYPE,XINT, XFASTINT, XUINT) 983 (XLI, XIL, XHASH, XTYPE, XINT, XFASTINT, XUINT)
511 (make_number, XPNTR, XUNTAG, EQ, XCONS, XVECTOR, XSTRING, XSYMBOL) 984 (make_number, XPNTR, XUNTAG, EQ, XCONS, XVECTOR, XSTRING, XSYMBOL)
512 (XFLOAT, XPROCESS, XWINDOW, XTERMINAL, XSUBR, XBUFFER, XCHAR_TABLE) 985 (XFLOAT, XPROCESS, XWINDOW, XTERMINAL, XSUBR, XBUFFER, XCHAR_TABLE)
513 (XSUB_CHAR_TABLE, XBOOL_VECTOR, make_lisp_ptr, CHECK_TYPE) 986 (XSUB_CHAR_TABLE, XBOOL_VECTOR, make_lisp_ptr, CHECK_TYPE)
diff --git a/src/alloc.c b/src/alloc.c
index b625e1f27e0..b71cdb98d78 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -247,10 +247,6 @@ enum mem_type
247 247
248#if GC_MARK_STACK || defined GC_MALLOC_CHECK 248#if GC_MARK_STACK || defined GC_MALLOC_CHECK
249 249
250#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
251#include <stdio.h> /* For fprintf. */
252#endif
253
254/* A unique object in pure space used to make some Lisp objects 250/* A unique object in pure space used to make some Lisp objects
255 on free lists recognizable in O(1). */ 251 on free lists recognizable in O(1). */
256 252
@@ -4745,7 +4741,7 @@ valid_pointer_p (void *p)
4745 Unfortunately, we cannot use NULL_DEVICE here, as emacs_write may 4741 Unfortunately, we cannot use NULL_DEVICE here, as emacs_write may
4746 not validate p in that case. */ 4742 not validate p in that case. */
4747 4743
4748 if (pipe (fd) == 0) 4744 if (pipe2 (fd, O_CLOEXEC) == 0)
4749 { 4745 {
4750 bool valid = emacs_write (fd[1], (char *) p, 16) == 16; 4746 bool valid = emacs_write (fd[1], (char *) p, 16) == 16;
4751 emacs_close (fd[1]); 4747 emacs_close (fd[1]);
diff --git a/src/atimer.c b/src/atimer.c
index 73c7aa5686b..bb5294670d3 100644
--- a/src/atimer.c
+++ b/src/atimer.c
@@ -336,7 +336,7 @@ schedule_atimer (struct atimer *t)
336 struct atimer *a = atimers, *prev = NULL; 336 struct atimer *a = atimers, *prev = NULL;
337 337
338 /* Look for the first atimer that is ripe after T. */ 338 /* Look for the first atimer that is ripe after T. */
339 while (a && EMACS_TIME_GT (t->expiration, a->expiration)) 339 while (a && EMACS_TIME_LT (a->expiration, t->expiration))
340 prev = a, a = a->next; 340 prev = a, a = a->next;
341 341
342 /* Insert T in front of the atimer found, if any. */ 342 /* Insert T in front of the atimer found, if any. */
diff --git a/src/buffer.c b/src/buffer.c
index 3bb80c66ee6..44371144687 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -4612,7 +4612,6 @@ evaporate_overlays (ptrdiff_t pos)
4612 4612
4613#ifdef USE_MMAP_FOR_BUFFERS 4613#ifdef USE_MMAP_FOR_BUFFERS
4614 4614
4615#include <sys/types.h>
4616#include <sys/mman.h> 4615#include <sys/mman.h>
4617 4616
4618#ifndef MAP_ANON 4617#ifndef MAP_ANON
@@ -4627,8 +4626,6 @@ evaporate_overlays (ptrdiff_t pos)
4627#define MAP_FAILED ((void *) -1) 4626#define MAP_FAILED ((void *) -1)
4628#endif 4627#endif
4629 4628
4630#include <stdio.h>
4631
4632#if MAP_ANON == 0 4629#if MAP_ANON == 0
4633#include <fcntl.h> 4630#include <fcntl.h>
4634#endif 4631#endif
@@ -4738,7 +4735,7 @@ mmap_init (void)
4738 if (mmap_fd <= 0) 4735 if (mmap_fd <= 0)
4739 { 4736 {
4740 /* No anonymous mmap -- we need the file descriptor. */ 4737 /* No anonymous mmap -- we need the file descriptor. */
4741 mmap_fd = open ("/dev/zero", O_RDONLY); 4738 mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0);
4742 if (mmap_fd == -1) 4739 if (mmap_fd == -1)
4743 fatal ("Cannot open /dev/zero: %s", emacs_strerror (errno)); 4740 fatal ("Cannot open /dev/zero: %s", emacs_strerror (errno));
4744 } 4741 }
@@ -6107,6 +6104,11 @@ and is the visited file's modification time, as of that time. If the
6107modification time of the most recent save is different, this entry is 6104modification time of the most recent save is different, this entry is
6108obsolete. 6105obsolete.
6109 6106
6107An entry (t . 0) means means the buffer was previously unmodified but
6108its time stamp was unknown because it was not associated with a file.
6109An entry (t . -1) is similar, except that it means the buffer's visited
6110file did not exist.
6111
6110An entry (nil PROPERTY VALUE BEG . END) indicates that a text property 6112An entry (nil PROPERTY VALUE BEG . END) indicates that a text property
6111was modified between BEG and END. PROPERTY is the property name, 6113was modified between BEG and END. PROPERTY is the property name,
6112and VALUE is the old value. 6114and VALUE is the old value.
diff --git a/src/bytecode.c b/src/bytecode.c
index d95c53bf055..c79027597f8 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -59,7 +59,8 @@ by Hallvard:
59 indirect threaded, using GCC's computed goto extension. This code, 59 indirect threaded, using GCC's computed goto extension. This code,
60 as currently implemented, is incompatible with BYTE_CODE_SAFE and 60 as currently implemented, is incompatible with BYTE_CODE_SAFE and
61 BYTE_CODE_METER. */ 61 BYTE_CODE_METER. */
62#if defined (__GNUC__) && !defined (BYTE_CODE_SAFE) && !defined (BYTE_CODE_METER) 62#if (defined __GNUC__ && !defined __STRICT_ANSI__ \
63 && !defined BYTE_CODE_SAFE && !defined BYTE_CODE_METER)
63#define BYTE_CODE_THREADED 64#define BYTE_CODE_THREADED
64#endif 65#endif
65 66
@@ -285,8 +286,10 @@ enum byte_code_op
285 286
286#ifdef BYTE_CODE_SAFE 287#ifdef BYTE_CODE_SAFE
287 Bscan_buffer = 0153, /* No longer generated as of v18. */ 288 Bscan_buffer = 0153, /* No longer generated as of v18. */
288 Bset_mark = 0163 /* this loser is no longer generated as of v18 */ 289 Bset_mark = 0163, /* this loser is no longer generated as of v18 */
289#endif 290#endif
291
292 B__dummy__ = 0 /* Pacify C89. */
290}; 293};
291 294
292/* Whether to maintain a `top' and `bottom' field in the stack frame. */ 295/* Whether to maintain a `top' and `bottom' field in the stack frame. */
diff --git a/src/callproc.c b/src/callproc.c
index f0aa8222342..cdf92422b4d 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -31,6 +31,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
31 31
32#ifdef WINDOWSNT 32#ifdef WINDOWSNT
33#define NOMINMAX 33#define NOMINMAX
34#include <sys/socket.h> /* for fcntl */
34#include <windows.h> 35#include <windows.h>
35#include "w32.h" 36#include "w32.h"
36#define _P_NOWAIT 1 /* from process.h */ 37#define _P_NOWAIT 1 /* from process.h */
@@ -186,6 +187,12 @@ call_process_cleanup (Lisp_Object arg)
186 return Qnil; 187 return Qnil;
187} 188}
188 189
190#ifdef DOS_NT
191static mode_t const default_output_mode = S_IREAD | S_IWRITE;
192#else
193static mode_t const default_output_mode = 0666;
194#endif
195
189DEFUN ("call-process", Fcall_process, Scall_process, 1, MANY, 0, 196DEFUN ("call-process", Fcall_process, Scall_process, 1, MANY, 0,
190 doc: /* Call PROGRAM synchronously in separate process. 197 doc: /* Call PROGRAM synchronously in separate process.
191The remaining arguments are optional. 198The remaining arguments are optional.
@@ -407,18 +414,15 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
407 414
408 if (STRINGP (output_file)) 415 if (STRINGP (output_file))
409 { 416 {
410#ifdef DOS_NT
411 fd_output = emacs_open (SSDATA (output_file), 417 fd_output = emacs_open (SSDATA (output_file),
412 O_WRONLY | O_TRUNC | O_CREAT | O_TEXT, 418 O_WRONLY | O_CREAT | O_TRUNC | O_TEXT,
413 S_IREAD | S_IWRITE); 419 default_output_mode);
414#else /* not DOS_NT */
415 fd_output = creat (SSDATA (output_file), 0666);
416#endif /* not DOS_NT */
417 if (fd_output < 0) 420 if (fd_output < 0)
418 { 421 {
422 int open_errno = errno;
419 output_file = DECODE_FILE (output_file); 423 output_file = DECODE_FILE (output_file);
420 report_file_error ("Opening process output file", 424 report_file_errno ("Opening process output file",
421 Fcons (output_file, Qnil)); 425 Fcons (output_file, Qnil), open_errno);
422 } 426 }
423 if (STRINGP (error_file) || NILP (error_file)) 427 if (STRINGP (error_file) || NILP (error_file))
424 output_to_buffer = 0; 428 output_to_buffer = 0;
@@ -427,16 +431,19 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
427 /* Search for program; barf if not found. */ 431 /* Search for program; barf if not found. */
428 { 432 {
429 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 433 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
434 int ok;
430 435
431 GCPRO4 (infile, buffer, current_dir, error_file); 436 GCPRO4 (infile, buffer, current_dir, error_file);
432 openp (Vexec_path, args[0], Vexec_suffixes, &path, make_number (X_OK)); 437 ok = openp (Vexec_path, args[0], Vexec_suffixes, &path, make_number (X_OK));
433 UNGCPRO; 438 UNGCPRO;
439 if (ok < 0)
440 {
441 int openp_errno = errno;
442 emacs_close (filefd);
443 report_file_errno ("Searching for program",
444 Fcons (args[0], Qnil), openp_errno);
445 }
434 } 446 }
435 if (NILP (path))
436 {
437 emacs_close (filefd);
438 report_file_error ("Searching for program", Fcons (args[0], Qnil));
439 }
440 447
441 /* If program file name starts with /: for quoting a magic name, 448 /* If program file name starts with /: for quoting a magic name,
442 discard that. */ 449 discard that. */
@@ -492,12 +499,15 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
492 strcat (tempfile, "/"); 499 strcat (tempfile, "/");
493 strcat (tempfile, "detmp.XXX"); 500 strcat (tempfile, "detmp.XXX");
494 mktemp (tempfile); 501 mktemp (tempfile);
495 outfilefd = creat (tempfile, S_IREAD | S_IWRITE); 502 outfilefd = emacs_open (tempfile, O_WRONLY | O_CREAT | O_TRUNC,
496 if (outfilefd < 0) { 503 S_IREAD | S_IWRITE);
497 emacs_close (filefd); 504 if (outfilefd < 0)
498 report_file_error ("Opening process output file", 505 {
499 Fcons (build_string (tempfile), Qnil)); 506 int open_errno = errno;
500 } 507 emacs_close (filefd);
508 report_file_errno ("Opening process output file",
509 Fcons (build_string (tempfile), Qnil), open_errno);
510 }
501 } 511 }
502 else 512 else
503 outfilefd = fd_output; 513 outfilefd = fd_output;
@@ -514,12 +524,11 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
514 { 524 {
515#ifndef MSDOS 525#ifndef MSDOS
516 int fd[2]; 526 int fd[2];
517 if (pipe (fd) == -1) 527 if (pipe2 (fd, O_CLOEXEC) != 0)
518 { 528 {
519 int pipe_errno = errno; 529 int pipe_errno = errno;
520 emacs_close (filefd); 530 emacs_close (filefd);
521 errno = pipe_errno; 531 report_file_errno ("Creating process pipe", Qnil, pipe_errno);
522 report_file_error ("Creating process pipe", Qnil);
523 } 532 }
524 fd0 = fd[0]; 533 fd0 = fd[0];
525 fd1 = fd[1]; 534 fd1 = fd[1];
@@ -535,18 +544,13 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
535 if (NILP (error_file)) 544 if (NILP (error_file))
536 fd_error = emacs_open (NULL_DEVICE, O_WRONLY, 0); 545 fd_error = emacs_open (NULL_DEVICE, O_WRONLY, 0);
537 else if (STRINGP (error_file)) 546 else if (STRINGP (error_file))
538 { 547 fd_error = emacs_open (SSDATA (error_file),
539#ifdef DOS_NT 548 O_WRONLY | O_CREAT | O_TRUNC | O_TEXT,
540 fd_error = emacs_open (SSDATA (error_file), 549 default_output_mode);
541 O_WRONLY | O_TRUNC | O_CREAT | O_TEXT,
542 S_IREAD | S_IWRITE);
543#else /* not DOS_NT */
544 fd_error = creat (SSDATA (error_file), 0666);
545#endif /* not DOS_NT */
546 }
547 550
548 if (fd_error < 0) 551 if (fd_error < 0)
549 { 552 {
553 int open_errno = errno;
550 emacs_close (filefd); 554 emacs_close (filefd);
551 if (fd0 != filefd) 555 if (fd0 != filefd)
552 emacs_close (fd0); 556 emacs_close (fd0);
@@ -559,7 +563,8 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
559 error_file = build_string (NULL_DEVICE); 563 error_file = build_string (NULL_DEVICE);
560 else if (STRINGP (error_file)) 564 else if (STRINGP (error_file))
561 error_file = DECODE_FILE (error_file); 565 error_file = DECODE_FILE (error_file);
562 report_file_error ("Cannot redirect stderr", Fcons (error_file, Qnil)); 566 report_file_errno ("Cannot redirect stderr",
567 Fcons (error_file, Qnil), open_errno);
563 } 568 }
564 569
565#ifdef MSDOS /* MW, July 1993 */ 570#ifdef MSDOS /* MW, July 1993 */
@@ -587,10 +592,12 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
587 fd0 = emacs_open (tempfile, O_RDONLY | O_BINARY, 0); 592 fd0 = emacs_open (tempfile, O_RDONLY | O_BINARY, 0);
588 if (fd0 < 0) 593 if (fd0 < 0)
589 { 594 {
595 int open_errno = errno;
590 unlink (tempfile); 596 unlink (tempfile);
591 emacs_close (filefd); 597 emacs_close (filefd);
592 report_file_error ("Cannot re-open temporary file", 598 report_file_errno ("Cannot re-open temporary file",
593 Fcons (build_string (tempfile), Qnil)); 599 Fcons (build_string (tempfile), Qnil),
600 open_errno);
594 } 601 }
595 } 602 }
596 else 603 else
@@ -708,10 +715,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
708 } 715 }
709 716
710 if (pid < 0) 717 if (pid < 0)
711 { 718 report_file_errno ("Doing vfork", Qnil, child_errno);
712 errno = child_errno;
713 report_file_error ("Doing vfork", Qnil);
714 }
715 719
716 if (INTEGERP (buffer)) 720 if (INTEGERP (buffer))
717 return unbind_to (count, Qnil); 721 return unbind_to (count, Qnil);
@@ -1037,29 +1041,29 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
1037 memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1); 1041 memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1);
1038 coding_systems = Qt; 1042 coding_systems = Qt;
1039 1043
1040#ifdef HAVE_MKSTEMP 1044#if defined HAVE_MKOSTEMP || defined HAVE_MKSTEMP
1041 { 1045 {
1042 int fd; 1046 int fd, open_errno;
1043 1047
1044 block_input (); 1048 block_input ();
1049# ifdef HAVE_MKOSTEMP
1050 fd = mkostemp (tempfile, O_CLOEXEC);
1051# else
1045 fd = mkstemp (tempfile); 1052 fd = mkstemp (tempfile);
1053# endif
1054 open_errno = errno;
1046 unblock_input (); 1055 unblock_input ();
1047 if (fd == -1) 1056 if (fd < 0)
1048 report_file_error ("Failed to open temporary file", 1057 report_file_errno ("Failed to open temporary file",
1049 Fcons (build_string (tempfile), Qnil)); 1058 Fcons (build_string (tempfile), Qnil), open_errno);
1050 else 1059 emacs_close (fd);
1051 close (fd);
1052 } 1060 }
1053#else 1061#else
1054 errno = 0; 1062 errno = EEXIST;
1055 mktemp (tempfile); 1063 mktemp (tempfile);
1056 if (!*tempfile) 1064 if (!*tempfile)
1057 { 1065 report_file_error ("Failed to open temporary file using pattern",
1058 if (!errno) 1066 Fcons (pattern, Qnil));
1059 errno = EEXIST;
1060 report_file_error ("Failed to open temporary file using pattern",
1061 Fcons (pattern, Qnil));
1062 }
1063#endif 1067#endif
1064 1068
1065 filename_string = build_string (tempfile); 1069 filename_string = build_string (tempfile);
@@ -1185,15 +1189,6 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1185 1189
1186 pid_t pid = getpid (); 1190 pid_t pid = getpid ();
1187 1191
1188 /* Close Emacs's descriptors that this process should not have. */
1189 close_process_descs ();
1190
1191 /* DOS_NT isn't in a vfork, so if we are in the middle of load-file,
1192 we will lose if we call close_load_descs here. */
1193#ifndef DOS_NT
1194 close_load_descs ();
1195#endif
1196
1197 /* Note that use of alloca is always safe here. It's obvious for systems 1192 /* Note that use of alloca is always safe here. It's obvious for systems
1198 that do not have true vfork or that have true (stack) alloca. 1193 that do not have true vfork or that have true (stack) alloca.
1199 If using vfork and C_ALLOCA (when Emacs used to include 1194 If using vfork and C_ALLOCA (when Emacs used to include
@@ -1226,7 +1221,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1226 are changed between the check and this chdir, but we should 1221 are changed between the check and this chdir, but we should
1227 at least check. */ 1222 at least check. */
1228 if (chdir (temp) < 0) 1223 if (chdir (temp) < 0)
1229 _exit (errno); 1224 _exit (EXIT_CANCELED);
1230#else /* DOS_NT */ 1225#else /* DOS_NT */
1231 /* Get past the drive letter, so that d:/ is left alone. */ 1226 /* Get past the drive letter, so that d:/ is left alone. */
1232 if (i > 2 && IS_DEVICE_SEP (temp[1]) && IS_DIRECTORY_SEP (temp[2])) 1227 if (i > 2 && IS_DEVICE_SEP (temp[1]) && IS_DIRECTORY_SEP (temp[2]))
@@ -1351,28 +1346,24 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1351 } 1346 }
1352 1347
1353#ifndef MSDOS 1348#ifndef MSDOS
1354 emacs_close (0); 1349 /* Redirect file descriptors and clear the close-on-exec flag on the
1355 emacs_close (1); 1350 redirected ones. IN, OUT, and ERR are close-on-exec so they
1356 emacs_close (2); 1351 need not be closed explicitly. */
1357
1358 dup2 (in, 0); 1352 dup2 (in, 0);
1359 dup2 (out, 1); 1353 dup2 (out, 1);
1360 dup2 (err, 2); 1354 dup2 (err, 2);
1361 emacs_close (in);
1362 if (out != in)
1363 emacs_close (out);
1364 if (err != in && err != out)
1365 emacs_close (err);
1366 1355
1367 setpgid (0, 0); 1356 setpgid (0, 0);
1368 tcsetpgrp (0, pid); 1357 tcsetpgrp (0, pid);
1369 1358
1370 execve (new_argv[0], new_argv, env); 1359 execve (new_argv[0], new_argv, env);
1371 1360
1372 emacs_write (1, "Can't exec program: ", 20); 1361 /* Don't output the program name here, as it can be arbitrarily long,
1373 emacs_write (1, new_argv[0], strlen (new_argv[0])); 1362 and a long write from a vforked child to its parent can cause a
1374 emacs_write (1, "\n", 1); 1363 deadlock. */
1375 _exit (1); 1364 emacs_perror ("child process");
1365
1366 _exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
1376 1367
1377#else /* MSDOS */ 1368#else /* MSDOS */
1378 pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env); 1369 pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env);
@@ -1387,7 +1378,8 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1387 1378
1388#ifndef WINDOWSNT 1379#ifndef WINDOWSNT
1389/* Move the file descriptor FD so that its number is not less than MINFD. 1380/* Move the file descriptor FD so that its number is not less than MINFD.
1390 If the file descriptor is moved at all, the original is freed. */ 1381 If the file descriptor is moved at all, the original is closed on MSDOS,
1382 but not elsewhere as the caller will close it anyway. */
1391static int 1383static int
1392relocate_fd (int fd, int minfd) 1384relocate_fd (int fd, int minfd)
1393{ 1385{
@@ -1395,18 +1387,15 @@ relocate_fd (int fd, int minfd)
1395 return fd; 1387 return fd;
1396 else 1388 else
1397 { 1389 {
1398 int new = fcntl (fd, F_DUPFD, minfd); 1390 int new = fcntl (fd, F_DUPFD_CLOEXEC, minfd);
1399 if (new == -1) 1391 if (new == -1)
1400 { 1392 {
1401 const char *message_1 = "Error while setting up child: "; 1393 emacs_perror ("while setting up child");
1402 const char *errmessage = strerror (errno); 1394 _exit (EXIT_CANCELED);
1403 const char *message_2 = "\n";
1404 emacs_write (2, message_1, strlen (message_1));
1405 emacs_write (2, errmessage, strlen (errmessage));
1406 emacs_write (2, message_2, strlen (message_2));
1407 _exit (1);
1408 } 1395 }
1396#ifdef MSDOS
1409 emacs_close (fd); 1397 emacs_close (fd);
1398#endif
1410 return new; 1399 return new;
1411 } 1400 }
1412} 1401}
diff --git a/src/coding.c b/src/coding.c
index 1ab59294b98..a1494ad38aa 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -11218,6 +11218,8 @@ character.");
11218 plist[13] = build_pure_c_string ("No conversion on encoding, automatic conversion on decoding."); 11218 plist[13] = build_pure_c_string ("No conversion on encoding, automatic conversion on decoding.");
11219 plist[15] = args[coding_arg_eol_type] = Qnil; 11219 plist[15] = args[coding_arg_eol_type] = Qnil;
11220 args[coding_arg_plist] = Flist (16, plist); 11220 args[coding_arg_plist] = Flist (16, plist);
11221 args[coding_arg_undecided_inhibit_null_byte_detection] = make_number (0);
11222 args[coding_arg_undecided_inhibit_iso_escape_detection] = make_number (0);
11221 Fdefine_coding_system_internal (coding_arg_undecided_max, args); 11223 Fdefine_coding_system_internal (coding_arg_undecided_max, args);
11222 } 11224 }
11223 11225
diff --git a/src/cygw32.c b/src/cygw32.c
index a7dbdaed615..bbc3a49fd88 100644
--- a/src/cygw32.c
+++ b/src/cygw32.c
@@ -35,7 +35,7 @@ static void
35chdir_to_default_directory () 35chdir_to_default_directory ()
36{ 36{
37 Lisp_Object new_cwd; 37 Lisp_Object new_cwd;
38 int old_cwd_fd = open (".", O_RDONLY | O_DIRECTORY); 38 int old_cwd_fd = emacs_open (".", O_RDONLY | O_DIRECTORY, 0);
39 39
40 if (old_cwd_fd == -1) 40 if (old_cwd_fd == -1)
41 error ("could not open current directory: %s", strerror (errno)); 41 error ("could not open current directory: %s", strerror (errno));
diff --git a/src/data.c b/src/data.c
index 955c39727bb..dedbd51f36e 100644
--- a/src/data.c
+++ b/src/data.c
@@ -377,7 +377,8 @@ DEFUN ("stringp", Fstringp, Sstringp, 1, 1, 0,
377 377
378DEFUN ("multibyte-string-p", Fmultibyte_string_p, Smultibyte_string_p, 378DEFUN ("multibyte-string-p", Fmultibyte_string_p, Smultibyte_string_p,
379 1, 1, 0, 379 1, 1, 0,
380 doc: /* Return t if OBJECT is a multibyte string. */) 380 doc: /* Return t if OBJECT is a multibyte string.
381Return nil if OBJECT is either a unibyte string, or not a string. */)
381 (Lisp_Object object) 382 (Lisp_Object object)
382{ 383{
383 if (STRINGP (object) && STRING_MULTIBYTE (object)) 384 if (STRINGP (object) && STRING_MULTIBYTE (object))
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 3ec3c28431b..523544d56ca 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -142,7 +142,10 @@ static bool xd_in_read_queued_messages = 0;
142 } while (0) 142 } while (0)
143 143
144#else /* !DBUS_DEBUG */ 144#else /* !DBUS_DEBUG */
145#define XD_DEBUG_MESSAGE(...) \ 145# if __STDC_VERSION__ < 199901
146# define XD_DEBUG_MESSAGE (void) /* Pre-C99 compilers cannot debug. */
147# else
148# define XD_DEBUG_MESSAGE(...) \
146 do { \ 149 do { \
147 if (!NILP (Vdbus_debug)) \ 150 if (!NILP (Vdbus_debug)) \
148 { \ 151 { \
@@ -151,7 +154,8 @@ static bool xd_in_read_queued_messages = 0;
151 message ("%s: %s", __func__, s); \ 154 message ("%s: %s", __func__, s); \
152 } \ 155 } \
153 } while (0) 156 } while (0)
154#define XD_DEBUG_VALID_LISP_OBJECT_P(object) 157# endif
158# define XD_DEBUG_VALID_LISP_OBJECT_P(object)
155#endif 159#endif
156 160
157/* Check whether TYPE is a basic DBusType. */ 161/* Check whether TYPE is a basic DBusType. */
diff --git a/src/deps.mk b/src/deps.mk
index 83444474c59..39666dca515 100644
--- a/src/deps.mk
+++ b/src/deps.mk
@@ -190,7 +190,7 @@ sysdep.o: sysdep.c syssignal.h systty.h systime.h syswait.h blockinput.h \
190 frame.h atimer.h window.h msdos.h dosfns.h keyboard.h cm.h lisp.h \ 190 frame.h atimer.h window.h msdos.h dosfns.h keyboard.h cm.h lisp.h \
191 globals.h $(config_h) composite.h sysselect.h gnutls.h \ 191 globals.h $(config_h) composite.h sysselect.h gnutls.h \
192 ../lib/allocator.h ../lib/careadlinkat.h \ 192 ../lib/allocator.h ../lib/careadlinkat.h \
193 ../lib/unistd.h ../lib/ignore-value.h 193 ../lib/unistd.h
194term.o: term.c termchar.h termhooks.h termopts.h lisp.h globals.h $(config_h) \ 194term.o: term.c termchar.h termhooks.h termopts.h lisp.h globals.h $(config_h) \
195 cm.h frame.h disptab.h keyboard.h character.h charset.h coding.h ccl.h \ 195 cm.h frame.h disptab.h keyboard.h character.h charset.h coding.h ccl.h \
196 xterm.h msdos.h window.h keymap.h blockinput.h atimer.h systime.h \ 196 xterm.h msdos.h window.h keymap.h blockinput.h atimer.h systime.h \
diff --git a/src/dired.c b/src/dired.c
index 7bbfee7e5b0..b3348b0aff0 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -95,7 +95,7 @@ open_directory (char const *name, int *fdp)
95 d = fdopendir (fd); 95 d = fdopendir (fd);
96 opendir_errno = errno; 96 opendir_errno = errno;
97 if (! d) 97 if (! d)
98 close (fd); 98 emacs_close (fd);
99 } 99 }
100#endif 100#endif
101 101
diff --git a/src/dispextern.h b/src/dispextern.h
index d1e62c8ea16..e5a43d820dc 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3144,6 +3144,7 @@ struct glyph_row *row_containing_pos (struct window *, ptrdiff_t,
3144 struct glyph_row *, 3144 struct glyph_row *,
3145 struct glyph_row *, int); 3145 struct glyph_row *, int);
3146int line_bottom_y (struct it *); 3146int line_bottom_y (struct it *);
3147int default_line_pixel_height (struct window *);
3147int display_prop_intangible_p (Lisp_Object, Lisp_Object, ptrdiff_t, ptrdiff_t); 3148int display_prop_intangible_p (Lisp_Object, Lisp_Object, ptrdiff_t, ptrdiff_t);
3148void resize_echo_area_exactly (void); 3149void resize_echo_area_exactly (void);
3149int resize_mini_window (struct window *, int); 3150int resize_mini_window (struct window *, int);
@@ -3325,7 +3326,7 @@ int image_ascent (struct image *, struct face *, struct glyph_slice *);
3325void get_tty_size (int, int *, int *); 3326void get_tty_size (int, int *, int *);
3326void request_sigio (void); 3327void request_sigio (void);
3327void unrequest_sigio (void); 3328void unrequest_sigio (void);
3328int tabs_safe_p (int); 3329bool tabs_safe_p (int);
3329void init_baud_rate (int); 3330void init_baud_rate (int);
3330void init_sigio (int); 3331void init_sigio (int);
3331void ignore_sigio (void); 3332void ignore_sigio (void);
@@ -3497,11 +3498,12 @@ extern int string_cost (const char *);
3497extern int per_line_cost (const char *); 3498extern int per_line_cost (const char *);
3498extern void calculate_costs (struct frame *); 3499extern void calculate_costs (struct frame *);
3499extern void produce_glyphs (struct it *); 3500extern void produce_glyphs (struct it *);
3500extern int tty_capable_p (struct tty_display_info *, unsigned, unsigned long, unsigned long); 3501extern bool tty_capable_p (struct tty_display_info *, unsigned,
3502 unsigned long, unsigned long);
3501extern void set_tty_color_mode (struct tty_display_info *, struct frame *); 3503extern void set_tty_color_mode (struct tty_display_info *, struct frame *);
3502extern struct terminal *get_named_tty (const char *); 3504extern struct terminal *get_named_tty (const char *);
3503extern void create_tty_output (struct frame *); 3505extern void create_tty_output (struct frame *);
3504extern struct terminal *init_tty (const char *, const char *, int); 3506extern struct terminal *init_tty (const char *, const char *, bool);
3505extern void tty_append_glyph (struct it *); 3507extern void tty_append_glyph (struct it *);
3506 3508
3507 3509
diff --git a/src/dispnew.c b/src/dispnew.c
index ab73b6403ee..7db0a46d6da 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -21,7 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 21
22#define DISPEXTERN_INLINE EXTERN_INLINE 22#define DISPEXTERN_INLINE EXTERN_INLINE
23 23
24#include <stdio.h> 24#include "sysstdio.h"
25#include <unistd.h> 25#include <unistd.h>
26 26
27#include "lisp.h" 27#include "lisp.h"
@@ -216,6 +216,7 @@ static void
216add_window_display_history (struct window *w, const char *msg, bool paused_p) 216add_window_display_history (struct window *w, const char *msg, bool paused_p)
217{ 217{
218 char *buf; 218 char *buf;
219 void *ptr = w;
219 220
220 if (history_idx >= REDISPLAY_HISTORY_SIZE) 221 if (history_idx >= REDISPLAY_HISTORY_SIZE)
221 history_idx = 0; 222 history_idx = 0;
@@ -225,7 +226,7 @@ add_window_display_history (struct window *w, const char *msg, bool paused_p)
225 snprintf (buf, sizeof redisplay_history[0].trace, 226 snprintf (buf, sizeof redisplay_history[0].trace,
226 "%"pMu": window %p (`%s')%s\n%s", 227 "%"pMu": window %p (`%s')%s\n%s",
227 history_tick++, 228 history_tick++,
228 w, 229 ptr,
229 ((BUFFERP (w->contents) 230 ((BUFFERP (w->contents)
230 && STRINGP (BVAR (XBUFFER (w->contents), name))) 231 && STRINGP (BVAR (XBUFFER (w->contents), name)))
231 ? SSDATA (BVAR (XBUFFER (w->contents), name)) 232 ? SSDATA (BVAR (XBUFFER (w->contents), name))
@@ -242,6 +243,7 @@ add_window_display_history (struct window *w, const char *msg, bool paused_p)
242static void add_frame_display_history (struct frame *f, int paused_p) 243static void add_frame_display_history (struct frame *f, int paused_p)
243{ 244{
244 char *buf; 245 char *buf;
246 void *ptr = f;
245 247
246 if (history_idx >= REDISPLAY_HISTORY_SIZE) 248 if (history_idx >= REDISPLAY_HISTORY_SIZE)
247 history_idx = 0; 249 history_idx = 0;
@@ -250,7 +252,7 @@ static void add_frame_display_history (struct frame *f, int paused_p)
250 252
251 sprintf (buf, "%"pMu": update frame %p%s", 253 sprintf (buf, "%"pMu": update frame %p%s",
252 history_tick++, 254 history_tick++,
253 f, paused_p ? " ***paused***" : ""); 255 ptr, paused_p ? " ***paused***" : "");
254} 256}
255 257
256 258
@@ -5616,17 +5618,17 @@ FILE = nil means just close any termscript file currently open. */)
5616 tty = CURTTY (); 5618 tty = CURTTY ();
5617 5619
5618 if (tty->termscript != 0) 5620 if (tty->termscript != 0)
5619 { 5621 {
5620 block_input (); 5622 block_input ();
5621 fclose (tty->termscript); 5623 fclose (tty->termscript);
5622 unblock_input (); 5624 tty->termscript = 0;
5623 } 5625 unblock_input ();
5624 tty->termscript = 0; 5626 }
5625 5627
5626 if (! NILP (file)) 5628 if (! NILP (file))
5627 { 5629 {
5628 file = Fexpand_file_name (file, Qnil); 5630 file = Fexpand_file_name (file, Qnil);
5629 tty->termscript = fopen (SSDATA (file), "w"); 5631 tty->termscript = emacs_fopen (SSDATA (file), "w");
5630 if (tty->termscript == 0) 5632 if (tty->termscript == 0)
5631 report_file_error ("Opening termscript", Fcons (file, Qnil)); 5633 report_file_error ("Opening termscript", Fcons (file, Qnil));
5632 } 5634 }
diff --git a/src/emacs.c b/src/emacs.c
index a1ad2d44b3b..08609ee6a08 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -28,12 +28,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28#include <unistd.h> 28#include <unistd.h>
29 29
30#include <close-stream.h> 30#include <close-stream.h>
31#include <ignore-value.h>
32 31
33#include "lisp.h" 32#include "lisp.h"
34 33
35#ifdef WINDOWSNT 34#ifdef WINDOWSNT
36#include <fcntl.h> 35#include <fcntl.h>
36#include <sys/socket.h>
37#include "w32.h" 37#include "w32.h"
38#include "w32heap.h" 38#include "w32heap.h"
39#endif 39#endif
@@ -204,10 +204,10 @@ int initial_argc;
204static void sort_args (int argc, char **argv); 204static void sort_args (int argc, char **argv);
205static void syms_of_emacs (void); 205static void syms_of_emacs (void);
206 206
207/* MSVC needs each string be shorter than 2048 bytes, so the usage 207/* C89 needs each string be at most 509 characters, so the usage
208 strings below are split to not overflow this limit. */ 208 strings below are split to not overflow this limit. */
209#define USAGE1 "\ 209static char const *const usage_message[] =
210Usage: %s [OPTION-OR-FILENAME]...\n\ 210 { "\
211\n\ 211\n\
212Run Emacs, the extensible, customizable, self-documenting real-time\n\ 212Run Emacs, the extensible, customizable, self-documenting real-time\n\
213display editor. The recommended way to start Emacs for normal editing\n\ 213display editor. The recommended way to start Emacs for normal editing\n\
@@ -218,11 +218,15 @@ read the main documentation for these command-line arguments.\n\
218\n\ 218\n\
219Initialization options:\n\ 219Initialization options:\n\
220\n\ 220\n\
221",
222 "\
221--batch do not do interactive display; implies -q\n\ 223--batch do not do interactive display; implies -q\n\
222--chdir DIR change to directory DIR\n\ 224--chdir DIR change to directory DIR\n\
223--daemon start a server in the background\n\ 225--daemon start a server in the background\n\
224--debug-init enable Emacs Lisp debugger for init file\n\ 226--debug-init enable Emacs Lisp debugger for init file\n\
225--display, -d DISPLAY use X server DISPLAY\n\ 227--display, -d DISPLAY use X server DISPLAY\n\
228",
229 "\
226--no-desktop do not load a saved desktop\n\ 230--no-desktop do not load a saved desktop\n\
227--no-init-file, -q load neither ~/.emacs nor default.el\n\ 231--no-init-file, -q load neither ~/.emacs nor default.el\n\
228--no-shared-memory, -nl do not use shared memory\n\ 232--no-shared-memory, -nl do not use shared memory\n\
@@ -230,14 +234,16 @@ Initialization options:\n\
230--no-site-lisp, -nsl do not add site-lisp directories to load-path\n\ 234--no-site-lisp, -nsl do not add site-lisp directories to load-path\n\
231--no-splash do not display a splash screen on startup\n\ 235--no-splash do not display a splash screen on startup\n\
232--no-window-system, -nw do not communicate with X, ignoring $DISPLAY\n\ 236--no-window-system, -nw do not communicate with X, ignoring $DISPLAY\n\
237",
238 "\
233--quick, -Q equivalent to:\n\ 239--quick, -Q equivalent to:\n\
234 -q --no-site-file --no-site-lisp --no-splash\n\ 240 -q --no-site-file --no-site-lisp --no-splash\n\
235--script FILE run FILE as an Emacs Lisp script\n\ 241--script FILE run FILE as an Emacs Lisp script\n\
236--terminal, -t DEVICE use DEVICE for terminal I/O\n\ 242--terminal, -t DEVICE use DEVICE for terminal I/O\n\
237--user, -u USER load ~USER/.emacs instead of your own\n\ 243--user, -u USER load ~USER/.emacs instead of your own\n\
238\n%s" 244\n\
239 245",
240#define USAGE2 "\ 246 "\
241Action options:\n\ 247Action options:\n\
242\n\ 248\n\
243FILE visit FILE using find-file\n\ 249FILE visit FILE using find-file\n\
@@ -246,6 +252,8 @@ FILE visit FILE using find-file\n\
246--directory, -L DIR add DIR to variable load-path\n\ 252--directory, -L DIR add DIR to variable load-path\n\
247--eval EXPR evaluate Emacs Lisp expression EXPR\n\ 253--eval EXPR evaluate Emacs Lisp expression EXPR\n\
248--execute EXPR evaluate Emacs Lisp expression EXPR\n\ 254--execute EXPR evaluate Emacs Lisp expression EXPR\n\
255",
256 "\
249--file FILE visit FILE using find-file\n\ 257--file FILE visit FILE using find-file\n\
250--find-file FILE visit FILE using find-file\n\ 258--find-file FILE visit FILE using find-file\n\
251--funcall, -f FUNC call Emacs Lisp function FUNC with no arguments\n\ 259--funcall, -f FUNC call Emacs Lisp function FUNC with no arguments\n\
@@ -253,9 +261,9 @@ FILE visit FILE using find-file\n\
253--kill exit without asking for confirmation\n\ 261--kill exit without asking for confirmation\n\
254--load, -l FILE load Emacs Lisp FILE using the load function\n\ 262--load, -l FILE load Emacs Lisp FILE using the load function\n\
255--visit FILE visit FILE using find-file\n\ 263--visit FILE visit FILE using find-file\n\
256\n" 264\n\
257 265",
258#define USAGE3 "\ 266 "\
259Display options:\n\ 267Display options:\n\
260\n\ 268\n\
261--background-color, -bg COLOR window background color\n\ 269--background-color, -bg COLOR window background color\n\
@@ -263,6 +271,8 @@ Display options:\n\
263 used for debugging Emacs\n\ 271 used for debugging Emacs\n\
264--border-color, -bd COLOR main border color\n\ 272--border-color, -bd COLOR main border color\n\
265--border-width, -bw WIDTH width of main border\n\ 273--border-width, -bw WIDTH width of main border\n\
274",
275 "\
266--color, --color=MODE override color mode for character terminals;\n\ 276--color, --color=MODE override color mode for character terminals;\n\
267 MODE defaults to `auto', and\n\ 277 MODE defaults to `auto', and\n\
268 can also be `never', `always',\n\ 278 can also be `never', `always',\n\
@@ -270,17 +280,23 @@ Display options:\n\
270--cursor-color, -cr COLOR color of the Emacs cursor indicating point\n\ 280--cursor-color, -cr COLOR color of the Emacs cursor indicating point\n\
271--font, -fn FONT default font; must be fixed-width\n\ 281--font, -fn FONT default font; must be fixed-width\n\
272--foreground-color, -fg COLOR window foreground color\n\ 282--foreground-color, -fg COLOR window foreground color\n\
283",
284 "\
273--fullheight, -fh make the first frame high as the screen\n\ 285--fullheight, -fh make the first frame high as the screen\n\
274--fullscreen, -fs make the first frame fullscreen\n\ 286--fullscreen, -fs make the first frame fullscreen\n\
275--fullwidth, -fw make the first frame wide as the screen\n\ 287--fullwidth, -fw make the first frame wide as the screen\n\
276--maximized, -mm make the first frame maximized\n\ 288--maximized, -mm make the first frame maximized\n\
277--geometry, -g GEOMETRY window geometry\n\ 289--geometry, -g GEOMETRY window geometry\n\
290",
291 "\
278--no-bitmap-icon, -nbi do not use picture of gnu for Emacs icon\n\ 292--no-bitmap-icon, -nbi do not use picture of gnu for Emacs icon\n\
279--iconic start Emacs in iconified state\n\ 293--iconic start Emacs in iconified state\n\
280--internal-border, -ib WIDTH width between text and main border\n\ 294--internal-border, -ib WIDTH width between text and main border\n\
281--line-spacing, -lsp PIXELS additional space to put between lines\n\ 295--line-spacing, -lsp PIXELS additional space to put between lines\n\
282--mouse-color, -ms COLOR mouse cursor color in Emacs window\n\ 296--mouse-color, -ms COLOR mouse cursor color in Emacs window\n\
283--name NAME title for initial Emacs frame\n\ 297--name NAME title for initial Emacs frame\n\
298",
299 "\
284--no-blinking-cursor, -nbc disable blinking cursor\n\ 300--no-blinking-cursor, -nbc disable blinking cursor\n\
285--reverse-video, -r, -rv switch foreground and background\n\ 301--reverse-video, -r, -rv switch foreground and background\n\
286--title, -T TITLE title for initial Emacs frame\n\ 302--title, -T TITLE title for initial Emacs frame\n\
@@ -289,9 +305,9 @@ Display options:\n\
289--parent-id XID set parent window\n\ 305--parent-id XID set parent window\n\
290--help display this help and exit\n\ 306--help display this help and exit\n\
291--version output version information and exit\n\ 307--version output version information and exit\n\
292\n" 308\n\
293 309",
294#define USAGE4 "\ 310 "\
295You can generally also specify long option names with a single -; for\n\ 311You can generally also specify long option names with a single -; for\n\
296example, -batch as well as --batch. You can use any unambiguous\n\ 312example, -batch as well as --batch. You can use any unambiguous\n\
297abbreviation for a --option.\n\ 313abbreviation for a --option.\n\
@@ -301,6 +317,7 @@ Emacs' operation. See the main documentation.\n\
301\n\ 317\n\
302Report bugs to bug-gnu-emacs@gnu.org. First, please see the Bugs\n\ 318Report bugs to bug-gnu-emacs@gnu.org. First, please see the Bugs\n\
303section of the Emacs manual or the file BUGS.\n" 319section of the Emacs manual or the file BUGS.\n"
320 };
304 321
305 322
306/* True if handling a fatal error already. */ 323/* True if handling a fatal error already. */
@@ -648,9 +665,7 @@ close_output_streams (void)
648{ 665{
649 if (close_stream (stdout) != 0) 666 if (close_stream (stdout) != 0)
650 { 667 {
651 fprintf (stderr, "Write error to standard output: %s\n", 668 emacs_perror ("Write error to standard output");
652 strerror (errno));
653 fflush (stderr);
654 _exit (EXIT_FAILURE); 669 _exit (EXIT_FAILURE);
655 } 670 }
656 671
@@ -791,7 +806,7 @@ main (int argc, char **argv)
791 execvp (argv[0], argv); 806 execvp (argv[0], argv);
792 807
793 /* If the exec fails, try to dump anyway. */ 808 /* If the exec fails, try to dump anyway. */
794 perror ("execvp"); 809 emacs_perror (argv[0]);
795 } 810 }
796#endif /* HAVE_PERSONALITY_LINUX32 */ 811#endif /* HAVE_PERSONALITY_LINUX32 */
797 812
@@ -892,7 +907,7 @@ main (int argc, char **argv)
892 emacs_close (0); 907 emacs_close (0);
893 emacs_close (1); 908 emacs_close (1);
894 result = emacs_open (term, O_RDWR, 0); 909 result = emacs_open (term, O_RDWR, 0);
895 if (result < 0 || dup (0) < 0) 910 if (result < 0 || fcntl (0, F_DUPFD_CLOEXEC, 1) < 0)
896 { 911 {
897 char *errstring = strerror (errno); 912 char *errstring = strerror (errno);
898 fprintf (stderr, "%s: %s: %s\n", argv[0], term, errstring); 913 fprintf (stderr, "%s: %s: %s\n", argv[0], term, errstring);
@@ -939,9 +954,10 @@ main (int argc, char **argv)
939 /* Handle the --help option, which gives a usage message. */ 954 /* Handle the --help option, which gives a usage message. */
940 if (argmatch (argv, argc, "-help", "--help", 3, NULL, &skip_args)) 955 if (argmatch (argv, argc, "-help", "--help", 3, NULL, &skip_args))
941 { 956 {
942 printf (USAGE1, argv[0], USAGE2); 957 int i;
943 printf (USAGE3); 958 printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]);
944 printf (USAGE4); 959 for (i = 0; i < sizeof usage_message / sizeof *usage_message; i++)
960 fputs (usage_message[i], stdout);
945 exit (0); 961 exit (0);
946 } 962 }
947 963
@@ -972,7 +988,7 @@ main (int argc, char **argv)
972 use a pipe for synchronization. The parent waits for the child 988 use a pipe for synchronization. The parent waits for the child
973 to close its end of the pipe (using `daemon-initialized') 989 to close its end of the pipe (using `daemon-initialized')
974 before exiting. */ 990 before exiting. */
975 if (pipe (daemon_pipe) == -1) 991 if (pipe2 (daemon_pipe, O_CLOEXEC) != 0)
976 { 992 {
977 fprintf (stderr, "Cannot pipe!\n"); 993 fprintf (stderr, "Cannot pipe!\n");
978 exit (1); 994 exit (1);
@@ -997,7 +1013,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
997 char buf[1]; 1013 char buf[1];
998 1014
999 /* Close unused writing end of the pipe. */ 1015 /* Close unused writing end of the pipe. */
1000 close (daemon_pipe[1]); 1016 emacs_close (daemon_pipe[1]);
1001 1017
1002 /* Just wait for the child to close its end of the pipe. */ 1018 /* Just wait for the child to close its end of the pipe. */
1003 do 1019 do
@@ -1017,13 +1033,13 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1017 exit (1); 1033 exit (1);
1018 } 1034 }
1019 1035
1020 close (daemon_pipe[0]); 1036 emacs_close (daemon_pipe[0]);
1021 exit (0); 1037 exit (0);
1022 } 1038 }
1023 if (f < 0) 1039 if (f < 0)
1024 { 1040 {
1025 fprintf (stderr, "Cannot fork!\n"); 1041 emacs_perror ("fork");
1026 exit (1); 1042 exit (EXIT_CANCELED);
1027 } 1043 }
1028 1044
1029#ifdef DAEMON_MUST_EXEC 1045#ifdef DAEMON_MUST_EXEC
@@ -1040,14 +1056,14 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1040 if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr)) 1056 if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr))
1041 { 1057 {
1042 fprintf (stderr, "daemon: child name too long\n"); 1058 fprintf (stderr, "daemon: child name too long\n");
1043 exit (1); 1059 exit (EXIT_CANNOT_INVOKE);
1044 } 1060 }
1045 1061
1046 argv[skip_args] = fdStr; 1062 argv[skip_args] = fdStr;
1047 1063
1048 execvp (argv[0], argv); 1064 execvp (argv[0], argv);
1049 fprintf (stderr, "emacs daemon: exec failed: %d\n", errno); 1065 emacs_perror (argv[0]);
1050 exit (1); 1066 exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
1051 } 1067 }
1052 1068
1053 /* In exec'd: parse special dname into pipe and name info. */ 1069 /* In exec'd: parse special dname into pipe and name info. */
@@ -1055,7 +1071,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1055 || strlen (dname_arg) < 1 || strlen (dname_arg) > 70) 1071 || strlen (dname_arg) < 1 || strlen (dname_arg) > 70)
1056 { 1072 {
1057 fprintf (stderr, "emacs daemon: daemon name absent or too long\n"); 1073 fprintf (stderr, "emacs daemon: daemon name absent or too long\n");
1058 exit (1); 1074 exit (EXIT_CANNOT_INVOKE);
1059 } 1075 }
1060 dname_arg2[0] = '\0'; 1076 dname_arg2[0] = '\0';
1061 sscanf (dname_arg, "\n%d,%d\n%s", &(daemon_pipe[0]), &(daemon_pipe[1]), 1077 sscanf (dname_arg, "\n%d,%d\n%s", &(daemon_pipe[0]), &(daemon_pipe[1]),
@@ -1067,10 +1083,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1067 if (dname_arg) 1083 if (dname_arg)
1068 daemon_name = xstrdup (dname_arg); 1084 daemon_name = xstrdup (dname_arg);
1069 /* Close unused reading end of the pipe. */ 1085 /* Close unused reading end of the pipe. */
1070 close (daemon_pipe[0]); 1086 emacs_close (daemon_pipe[0]);
1071 /* Make sure that the used end of the pipe is closed on exec, so
1072 that it is not accessible to programs started from .emacs. */
1073 fcntl (daemon_pipe[1], F_SETFD, FD_CLOEXEC);
1074 1087
1075 setsid (); 1088 setsid ();
1076#else /* DOS_NT */ 1089#else /* DOS_NT */
@@ -1080,7 +1093,14 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1080 } 1093 }
1081 1094
1082#if defined HAVE_PTHREAD && !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC 1095#if defined HAVE_PTHREAD && !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC
1083 malloc_enable_thread (); 1096# ifndef CANNOT_DUMP
1097 /* Do not make gmalloc thread-safe when creating bootstrap-emacs, as
1098 that causes an infinite recursive loop with FreeBSD. But do make
1099 it thread-safe when creating emacs, otherwise bootstrap-emacs
1100 fails on Cygwin. See Bug#14569. */
1101 if (!noninteractive || initialized)
1102# endif
1103 malloc_enable_thread ();
1084#endif 1104#endif
1085 1105
1086 init_signals (dumping); 1106 init_signals (dumping);
@@ -1917,8 +1937,8 @@ shut_down_emacs (int sig, Lisp_Object stuff)
1917 char buf[sizeof format - 2 + INT_STRLEN_BOUND (int)]; 1937 char buf[sizeof format - 2 + INT_STRLEN_BOUND (int)];
1918 int buflen = sprintf (buf, format, sig); 1938 int buflen = sprintf (buf, format, sig);
1919 char const *sig_desc = safe_strsignal (sig); 1939 char const *sig_desc = safe_strsignal (sig);
1920 ignore_value (write (STDERR_FILENO, buf, buflen)); 1940 emacs_write (STDERR_FILENO, buf, buflen);
1921 ignore_value (write (STDERR_FILENO, sig_desc, strlen (sig_desc))); 1941 emacs_write (STDERR_FILENO, sig_desc, strlen (sig_desc));
1922 } 1942 }
1923 } 1943 }
1924 } 1944 }
@@ -2235,12 +2255,12 @@ from the parent process and its tty file descriptors. */)
2235 error ("This function can only be called after loading the init files"); 2255 error ("This function can only be called after loading the init files");
2236 2256
2237 /* Get rid of stdin, stdout and stderr. */ 2257 /* Get rid of stdin, stdout and stderr. */
2238 nfd = open ("/dev/null", O_RDWR); 2258 nfd = emacs_open ("/dev/null", O_RDWR, 0);
2239 err |= nfd < 0; 2259 err |= nfd < 0;
2240 err |= dup2 (nfd, 0) < 0; 2260 err |= dup2 (nfd, 0) < 0;
2241 err |= dup2 (nfd, 1) < 0; 2261 err |= dup2 (nfd, 1) < 0;
2242 err |= dup2 (nfd, 2) < 0; 2262 err |= dup2 (nfd, 2) < 0;
2243 err |= close (nfd) != 0; 2263 err |= emacs_close (nfd) != 0;
2244 2264
2245 /* Closing the pipe will notify the parent that it can exit. 2265 /* Closing the pipe will notify the parent that it can exit.
2246 FIXME: In case some other process inherited the pipe, closing it here 2266 FIXME: In case some other process inherited the pipe, closing it here
@@ -2250,7 +2270,7 @@ from the parent process and its tty file descriptors. */)
2250 call-process to make sure the pipe is never inherited by 2270 call-process to make sure the pipe is never inherited by
2251 subprocesses. */ 2271 subprocesses. */
2252 err |= write (daemon_pipe[1], "\n", 1) < 0; 2272 err |= write (daemon_pipe[1], "\n", 1) < 0;
2253 err |= close (daemon_pipe[1]) != 0; 2273 err |= emacs_close (daemon_pipe[1]) != 0;
2254 /* Set it to an invalid value so we know we've already run this function. */ 2274 /* Set it to an invalid value so we know we've already run this function. */
2255 daemon_pipe[1] = -1; 2275 daemon_pipe[1] = -1;
2256 2276
diff --git a/src/eval.c b/src/eval.c
index d3545add21d..0e231bdb285 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -114,6 +114,13 @@ Lisp_Object Vsignaling_function;
114 frame is half-initialized. */ 114 frame is half-initialized. */
115Lisp_Object inhibit_lisp_code; 115Lisp_Object inhibit_lisp_code;
116 116
117/* These would ordinarily be static, but they need to be visible to GDB. */
118bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE;
119Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE;
120Lisp_Object backtrace_function (union specbinding *) EXTERNALLY_VISIBLE;
121union specbinding *backtrace_next (union specbinding *) EXTERNALLY_VISIBLE;
122union specbinding *backtrace_top (void) EXTERNALLY_VISIBLE;
123
117static Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *); 124static Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *);
118static Lisp_Object apply_lambda (Lisp_Object fun, Lisp_Object args); 125static Lisp_Object apply_lambda (Lisp_Object fun, Lisp_Object args);
119 126
@@ -152,7 +159,7 @@ specpdl_func (union specbinding *pdl)
152 return pdl->unwind.func; 159 return pdl->unwind.func;
153} 160}
154 161
155static Lisp_Object 162Lisp_Object
156backtrace_function (union specbinding *pdl) 163backtrace_function (union specbinding *pdl)
157{ 164{
158 eassert (pdl->kind == SPECPDL_BACKTRACE); 165 eassert (pdl->kind == SPECPDL_BACKTRACE);
@@ -166,7 +173,7 @@ backtrace_nargs (union specbinding *pdl)
166 return pdl->bt.nargs; 173 return pdl->bt.nargs;
167} 174}
168 175
169static Lisp_Object * 176Lisp_Object *
170backtrace_args (union specbinding *pdl) 177backtrace_args (union specbinding *pdl)
171{ 178{
172 eassert (pdl->kind == SPECPDL_BACKTRACE); 179 eassert (pdl->kind == SPECPDL_BACKTRACE);
@@ -205,10 +212,6 @@ set_backtrace_debug_on_exit (union specbinding *pdl, bool doe)
205 212
206/* Helper functions to scan the backtrace. */ 213/* Helper functions to scan the backtrace. */
207 214
208bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE;
209union specbinding *backtrace_top (void) EXTERNALLY_VISIBLE;
210union specbinding *backtrace_next (union specbinding *pdl) EXTERNALLY_VISIBLE;
211
212bool 215bool
213backtrace_p (union specbinding *pdl) 216backtrace_p (union specbinding *pdl)
214{ return pdl >= specpdl; } 217{ return pdl >= specpdl; }
@@ -1993,38 +1996,52 @@ If LEXICAL is t, evaluate using lexical scoping. */)
1993 return unbind_to (count, eval_sub (form)); 1996 return unbind_to (count, eval_sub (form));
1994} 1997}
1995 1998
1999/* Grow the specpdl stack by one entry.
2000 The caller should have already initialized the entry.
2001 Signal an error on stack overflow.
2002
2003 Make sure that there is always one unused entry past the top of the
2004 stack, so that the just-initialized entry is safely unwound if
2005 memory exhausted and an error is signaled here. Also, allocate a
2006 never-used entry just before the bottom of the stack; sometimes its
2007 address is taken. */
2008
1996static void 2009static void
1997grow_specpdl (void) 2010grow_specpdl (void)
1998{ 2011{
1999 ptrdiff_t count = SPECPDL_INDEX (); 2012 specpdl_ptr++;
2000 ptrdiff_t max_size = min (max_specpdl_size, PTRDIFF_MAX - 1000); 2013
2001 union specbinding *pdlvec = specpdl - 1; 2014 if (specpdl_ptr == specpdl + specpdl_size)
2002 ptrdiff_t pdlvecsize = specpdl_size + 1;
2003 if (max_size <= specpdl_size)
2004 { 2015 {
2005 if (max_specpdl_size < 400) 2016 ptrdiff_t count = SPECPDL_INDEX ();
2006 max_size = max_specpdl_size = 400; 2017 ptrdiff_t max_size = min (max_specpdl_size, PTRDIFF_MAX - 1000);
2018 union specbinding *pdlvec = specpdl - 1;
2019 ptrdiff_t pdlvecsize = specpdl_size + 1;
2007 if (max_size <= specpdl_size) 2020 if (max_size <= specpdl_size)
2008 signal_error ("Variable binding depth exceeds max-specpdl-size", Qnil); 2021 {
2022 if (max_specpdl_size < 400)
2023 max_size = max_specpdl_size = 400;
2024 if (max_size <= specpdl_size)
2025 signal_error ("Variable binding depth exceeds max-specpdl-size",
2026 Qnil);
2027 }
2028 pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl);
2029 specpdl = pdlvec + 1;
2030 specpdl_size = pdlvecsize - 1;
2031 specpdl_ptr = specpdl + count;
2009 } 2032 }
2010 pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl);
2011 specpdl = pdlvec + 1;
2012 specpdl_size = pdlvecsize - 1;
2013 specpdl_ptr = specpdl + count;
2014} 2033}
2015 2034
2016void 2035void
2017record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs) 2036record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs)
2018{ 2037{
2019 eassert (nargs >= UNEVALLED); 2038 eassert (nargs >= UNEVALLED);
2020 if (specpdl_ptr == specpdl + specpdl_size)
2021 grow_specpdl ();
2022 specpdl_ptr->bt.kind = SPECPDL_BACKTRACE; 2039 specpdl_ptr->bt.kind = SPECPDL_BACKTRACE;
2023 specpdl_ptr->bt.debug_on_exit = false; 2040 specpdl_ptr->bt.debug_on_exit = false;
2024 specpdl_ptr->bt.function = function; 2041 specpdl_ptr->bt.function = function;
2025 specpdl_ptr->bt.args = args; 2042 specpdl_ptr->bt.args = args;
2026 specpdl_ptr->bt.nargs = nargs; 2043 specpdl_ptr->bt.nargs = nargs;
2027 specpdl_ptr++; 2044 grow_specpdl ();
2028} 2045}
2029 2046
2030/* Eval a sub-expression of the current expression (i.e. in the same 2047/* Eval a sub-expression of the current expression (i.e. in the same
@@ -3110,8 +3127,6 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3110 3127
3111 CHECK_SYMBOL (symbol); 3128 CHECK_SYMBOL (symbol);
3112 sym = XSYMBOL (symbol); 3129 sym = XSYMBOL (symbol);
3113 if (specpdl_ptr == specpdl + specpdl_size)
3114 grow_specpdl ();
3115 3130
3116 start: 3131 start:
3117 switch (sym->redirect) 3132 switch (sym->redirect)
@@ -3124,7 +3139,7 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3124 specpdl_ptr->let.kind = SPECPDL_LET; 3139 specpdl_ptr->let.kind = SPECPDL_LET;
3125 specpdl_ptr->let.symbol = symbol; 3140 specpdl_ptr->let.symbol = symbol;
3126 specpdl_ptr->let.old_value = SYMBOL_VAL (sym); 3141 specpdl_ptr->let.old_value = SYMBOL_VAL (sym);
3127 ++specpdl_ptr; 3142 grow_specpdl ();
3128 if (!sym->constant) 3143 if (!sym->constant)
3129 SET_SYMBOL_VAL (sym, value); 3144 SET_SYMBOL_VAL (sym, value);
3130 else 3145 else
@@ -3159,7 +3174,7 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3159 if (NILP (Flocal_variable_p (symbol, Qnil))) 3174 if (NILP (Flocal_variable_p (symbol, Qnil)))
3160 { 3175 {
3161 specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT; 3176 specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT;
3162 ++specpdl_ptr; 3177 grow_specpdl ();
3163 Fset_default (symbol, value); 3178 Fset_default (symbol, value);
3164 return; 3179 return;
3165 } 3180 }
@@ -3167,7 +3182,7 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3167 else 3182 else
3168 specpdl_ptr->let.kind = SPECPDL_LET; 3183 specpdl_ptr->let.kind = SPECPDL_LET;
3169 3184
3170 specpdl_ptr++; 3185 grow_specpdl ();
3171 set_internal (symbol, value, Qnil, 1); 3186 set_internal (symbol, value, Qnil, 1);
3172 break; 3187 break;
3173 } 3188 }
@@ -3178,12 +3193,10 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3178void 3193void
3179record_unwind_protect (Lisp_Object (*function) (Lisp_Object), Lisp_Object arg) 3194record_unwind_protect (Lisp_Object (*function) (Lisp_Object), Lisp_Object arg)
3180{ 3195{
3181 if (specpdl_ptr == specpdl + specpdl_size)
3182 grow_specpdl ();
3183 specpdl_ptr->unwind.kind = SPECPDL_UNWIND; 3196 specpdl_ptr->unwind.kind = SPECPDL_UNWIND;
3184 specpdl_ptr->unwind.func = function; 3197 specpdl_ptr->unwind.func = function;
3185 specpdl_ptr->unwind.arg = arg; 3198 specpdl_ptr->unwind.arg = arg;
3186 specpdl_ptr++; 3199 grow_specpdl ();
3187} 3200}
3188 3201
3189Lisp_Object 3202Lisp_Object
diff --git a/src/fileio.c b/src/fileio.c
index 4a14f5a5911..c3566390130 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -20,7 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20#include <config.h> 20#include <config.h>
21#include <limits.h> 21#include <limits.h>
22#include <fcntl.h> 22#include <fcntl.h>
23#include <stdio.h> 23#include "sysstdio.h"
24#include <sys/types.h> 24#include <sys/types.h>
25#include <sys/stat.h> 25#include <sys/stat.h>
26#include <unistd.h> 26#include <unistd.h>
@@ -55,7 +55,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
55#ifdef WINDOWSNT 55#ifdef WINDOWSNT
56#define NOMINMAX 1 56#define NOMINMAX 1
57#include <windows.h> 57#include <windows.h>
58#include <fcntl.h>
59#include <sys/file.h> 58#include <sys/file.h>
60#include "w32.h" 59#include "w32.h"
61#endif /* not WINDOWSNT */ 60#endif /* not WINDOWSNT */
@@ -63,7 +62,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
63#ifdef MSDOS 62#ifdef MSDOS
64#include "msdos.h" 63#include "msdos.h"
65#include <sys/param.h> 64#include <sys/param.h>
66#include <fcntl.h>
67#endif 65#endif
68 66
69#ifdef DOS_NT 67#ifdef DOS_NT
@@ -148,7 +146,7 @@ static Lisp_Object Qdelete_directory;
148#ifdef WINDOWSNT 146#ifdef WINDOWSNT
149#endif 147#endif
150 148
151Lisp_Object Qfile_error; 149Lisp_Object Qfile_error, Qfile_notify_error;
152static Lisp_Object Qfile_already_exists, Qfile_date_error; 150static Lisp_Object Qfile_already_exists, Qfile_date_error;
153static Lisp_Object Qexcl; 151static Lisp_Object Qexcl;
154Lisp_Object Qfile_name_history; 152Lisp_Object Qfile_name_history;
@@ -161,11 +159,13 @@ static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
161 struct coding_system *); 159 struct coding_system *);
162 160
163 161
162/* Signal a file-access failure. STRING describes the failure,
163 DATA the file that was involved, and ERRORNO the errno value. */
164
164void 165void
165report_file_error (const char *string, Lisp_Object data) 166report_file_errno (char const *string, Lisp_Object data, int errorno)
166{ 167{
167 Lisp_Object errstring; 168 Lisp_Object errstring;
168 int errorno = errno;
169 char *str; 169 char *str;
170 170
171 synchronize_system_messages_locale (); 171 synchronize_system_messages_locale ();
@@ -198,6 +198,12 @@ report_file_error (const char *string, Lisp_Object data)
198 } 198 }
199} 199}
200 200
201void
202report_file_error (char const *string, Lisp_Object data)
203{
204 report_file_errno (string, data, errno);
205}
206
201Lisp_Object 207Lisp_Object
202close_file_unwind (Lisp_Object fd) 208close_file_unwind (Lisp_Object fd)
203{ 209{
@@ -2021,11 +2027,8 @@ entries (depending on how Emacs was built). */)
2021 { 2027 {
2022 /* CopyFile doesn't set errno when it fails. By far the most 2028 /* CopyFile doesn't set errno when it fails. By far the most
2023 "popular" reason is that the target is read-only. */ 2029 "popular" reason is that the target is read-only. */
2024 if (GetLastError () == 5) 2030 report_file_errno ("Copying file", Fcons (file, Fcons (newname, Qnil)),
2025 errno = EACCES; 2031 GetLastError () == 5 ? EACCES : EPERM);
2026 else
2027 errno = EPERM;
2028 report_file_error ("Copying file", Fcons (file, Fcons (newname, Qnil)));
2029 } 2032 }
2030 /* CopyFile retains the timestamp by default. */ 2033 /* CopyFile retains the timestamp by default. */
2031 else if (NILP (keep_time)) 2034 else if (NILP (keep_time))
@@ -2086,36 +2089,25 @@ entries (depending on how Emacs was built). */)
2086 2089
2087 if (out_st.st_mode != 0 2090 if (out_st.st_mode != 0
2088 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino) 2091 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
2089 { 2092 report_file_errno ("Input and output files are the same",
2090 errno = 0; 2093 Fcons (file, Fcons (newname, Qnil)), 0);
2091 report_file_error ("Input and output files are the same",
2092 Fcons (file, Fcons (newname, Qnil)));
2093 }
2094 2094
2095 /* We can copy only regular files. */ 2095 /* We can copy only regular files. */
2096 if (!S_ISREG (st.st_mode)) 2096 if (!S_ISREG (st.st_mode))
2097 { 2097 report_file_errno ("Non-regular file", Fcons (file, Qnil),
2098 /* Get a better looking error message. */ 2098 S_ISDIR (st.st_mode) ? EISDIR : EINVAL);
2099 errno = S_ISDIR (st.st_mode) ? EISDIR : EINVAL;
2100 report_file_error ("Non-regular file", Fcons (file, Qnil));
2101 }
2102 2099
2103#ifdef MSDOS
2104 /* System's default file type was set to binary by _fmode in emacs.c. */
2105 ofd = emacs_open (SDATA (encoded_newname),
2106 O_WRONLY | O_TRUNC | O_CREAT
2107 | (NILP (ok_if_already_exists) ? O_EXCL : 0),
2108 S_IREAD | S_IWRITE);
2109#else /* not MSDOS */
2110 { 2100 {
2111 mode_t new_mask = !NILP (preserve_uid_gid) ? 0600 : 0666; 2101#ifndef MSDOS
2112 new_mask &= st.st_mode; 2102 int new_mask = st.st_mode & (!NILP (preserve_uid_gid) ? 0600 : 0666);
2103#else
2104 int new_mask = S_IREAD | S_IWRITE;
2105#endif
2113 ofd = emacs_open (SSDATA (encoded_newname), 2106 ofd = emacs_open (SSDATA (encoded_newname),
2114 (O_WRONLY | O_TRUNC | O_CREAT 2107 (O_WRONLY | O_TRUNC | O_CREAT
2115 | (NILP (ok_if_already_exists) ? O_EXCL : 0)), 2108 | (NILP (ok_if_already_exists) ? O_EXCL : 0)),
2116 new_mask); 2109 new_mask);
2117 } 2110 }
2118#endif /* not MSDOS */
2119 if (ofd < 0) 2111 if (ofd < 0)
2120 report_file_error ("Opening output file", Fcons (newname, Qnil)); 2112 report_file_error ("Opening output file", Fcons (newname, Qnil));
2121 2113
@@ -2124,7 +2116,7 @@ entries (depending on how Emacs was built). */)
2124 immediate_quit = 1; 2116 immediate_quit = 1;
2125 QUIT; 2117 QUIT;
2126 while ((n = emacs_read (ifd, buf, sizeof buf)) > 0) 2118 while ((n = emacs_read (ifd, buf, sizeof buf)) > 0)
2127 if (emacs_write (ofd, buf, n) != n) 2119 if (emacs_write_sig (ofd, buf, n) != n)
2128 report_file_error ("I/O error", Fcons (newname, Qnil)); 2120 report_file_error ("I/O error", Fcons (newname, Qnil));
2129 immediate_quit = 0; 2121 immediate_quit = 0;
2130 2122
@@ -2611,7 +2603,11 @@ Use `file-symlink-p' to test for such links. */)
2611 call the corresponding file handler. */ 2603 call the corresponding file handler. */
2612 handler = Ffind_file_name_handler (absname, Qfile_exists_p); 2604 handler = Ffind_file_name_handler (absname, Qfile_exists_p);
2613 if (!NILP (handler)) 2605 if (!NILP (handler))
2614 return call2 (handler, Qfile_exists_p, absname); 2606 {
2607 Lisp_Object result = call2 (handler, Qfile_exists_p, absname);
2608 errno = 0;
2609 return result;
2610 }
2615 2611
2616 absname = ENCODE_FILE (absname); 2612 absname = ENCODE_FILE (absname);
2617 2613
@@ -2708,7 +2704,6 @@ If there is no error, returns nil. */)
2708 (Lisp_Object filename, Lisp_Object string) 2704 (Lisp_Object filename, Lisp_Object string)
2709{ 2705{
2710 Lisp_Object handler, encoded_filename, absname; 2706 Lisp_Object handler, encoded_filename, absname;
2711 int fd;
2712 2707
2713 CHECK_STRING (filename); 2708 CHECK_STRING (filename);
2714 absname = Fexpand_file_name (filename, Qnil); 2709 absname = Fexpand_file_name (filename, Qnil);
@@ -2723,10 +2718,8 @@ If there is no error, returns nil. */)
2723 2718
2724 encoded_filename = ENCODE_FILE (absname); 2719 encoded_filename = ENCODE_FILE (absname);
2725 2720
2726 fd = emacs_open (SSDATA (encoded_filename), O_RDONLY, 0); 2721 if (faccessat (AT_FDCWD, SSDATA (encoded_filename), R_OK, AT_EACCESS) != 0)
2727 if (fd < 0)
2728 report_file_error (SSDATA (string), Fcons (filename, Qnil)); 2722 report_file_error (SSDATA (string), Fcons (filename, Qnil));
2729 emacs_close (fd);
2730 2723
2731 return Qnil; 2724 return Qnil;
2732} 2725}
@@ -2835,7 +2828,11 @@ searchable directory. */)
2835 call the corresponding file handler. */ 2828 call the corresponding file handler. */
2836 handler = Ffind_file_name_handler (absname, Qfile_accessible_directory_p); 2829 handler = Ffind_file_name_handler (absname, Qfile_accessible_directory_p);
2837 if (!NILP (handler)) 2830 if (!NILP (handler))
2838 return call2 (handler, Qfile_accessible_directory_p, absname); 2831 {
2832 Lisp_Object r = call2 (handler, Qfile_accessible_directory_p, absname);
2833 errno = 0;
2834 return r;
2835 }
2839 2836
2840 absname = ENCODE_FILE (absname); 2837 absname = ENCODE_FILE (absname);
2841 return file_accessible_directory_p (SSDATA (absname)) ? Qt : Qnil; 2838 return file_accessible_directory_p (SSDATA (absname)) ? Qt : Qnil;
@@ -3347,7 +3344,7 @@ otherwise, if FILE2 does not exist, the answer is t. */)
3347 if (stat (SSDATA (absname2), &st2) < 0) 3344 if (stat (SSDATA (absname2), &st2) < 0)
3348 return Qt; 3345 return Qt;
3349 3346
3350 return (EMACS_TIME_GT (get_stat_mtime (&st1), get_stat_mtime (&st2)) 3347 return (EMACS_TIME_LT (get_stat_mtime (&st2), get_stat_mtime (&st1))
3351 ? Qt : Qnil); 3348 ? Qt : Qnil);
3352} 3349}
3353 3350
@@ -4577,8 +4574,8 @@ by calling `format-decode', which see. */)
4577 && EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS) 4574 && EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS)
4578 { 4575 {
4579 /* If visiting nonexistent file, return nil. */ 4576 /* If visiting nonexistent file, return nil. */
4580 errno = save_errno; 4577 report_file_errno ("Opening input file", Fcons (orig_filename, Qnil),
4581 report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); 4578 save_errno);
4582 } 4579 }
4583 4580
4584 if (read_quit) 4581 if (read_quit)
@@ -4899,13 +4896,13 @@ This calls `write-region-annotate-functions' at the start, and
4899 4896
4900 if (desc < 0) 4897 if (desc < 0)
4901 { 4898 {
4899 int open_errno = errno;
4902#ifdef CLASH_DETECTION 4900#ifdef CLASH_DETECTION
4903 save_errno = errno;
4904 if (!auto_saving) unlock_file (lockname); 4901 if (!auto_saving) unlock_file (lockname);
4905 errno = save_errno;
4906#endif /* CLASH_DETECTION */ 4902#endif /* CLASH_DETECTION */
4907 UNGCPRO; 4903 UNGCPRO;
4908 report_file_error ("Opening output file", Fcons (filename, Qnil)); 4904 report_file_errno ("Opening output file", Fcons (filename, Qnil),
4905 open_errno);
4909 } 4906 }
4910 4907
4911 record_unwind_protect (close_file_unwind, make_number (desc)); 4908 record_unwind_protect (close_file_unwind, make_number (desc));
@@ -4915,13 +4912,13 @@ This calls `write-region-annotate-functions' at the start, and
4915 off_t ret = lseek (desc, offset, SEEK_SET); 4912 off_t ret = lseek (desc, offset, SEEK_SET);
4916 if (ret < 0) 4913 if (ret < 0)
4917 { 4914 {
4915 int lseek_errno = errno;
4918#ifdef CLASH_DETECTION 4916#ifdef CLASH_DETECTION
4919 save_errno = errno;
4920 if (!auto_saving) unlock_file (lockname); 4917 if (!auto_saving) unlock_file (lockname);
4921 errno = save_errno;
4922#endif /* CLASH_DETECTION */ 4918#endif /* CLASH_DETECTION */
4923 UNGCPRO; 4919 UNGCPRO;
4924 report_file_error ("Lseek error", Fcons (filename, Qnil)); 4920 report_file_errno ("Lseek error", Fcons (filename, Qnil),
4921 lseek_errno);
4925 } 4922 }
4926 } 4923 }
4927 4924
@@ -5319,12 +5316,10 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
5319 5316
5320 if (coding->produced > 0) 5317 if (coding->produced > 0)
5321 { 5318 {
5322 coding->produced 5319 char *buf = (STRINGP (coding->dst_object)
5323 -= emacs_write (desc, 5320 ? SSDATA (coding->dst_object)
5324 STRINGP (coding->dst_object) 5321 : (char *) BYTE_POS_ADDR (coding->dst_pos_byte));
5325 ? SSDATA (coding->dst_object) 5322 coding->produced -= emacs_write_sig (desc, buf, coding->produced);
5326 : (char *) BYTE_POS_ADDR (coding->dst_pos_byte),
5327 coding->produced);
5328 5323
5329 if (coding->produced) 5324 if (coding->produced)
5330 return 0; 5325 return 0;
@@ -5379,36 +5374,19 @@ See Info node `(elisp)Modification Time' for more details. */)
5379 return Qnil; 5374 return Qnil;
5380} 5375}
5381 5376
5382DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
5383 Sclear_visited_file_modtime, 0, 0, 0,
5384 doc: /* Clear out records of last mod time of visited file.
5385Next attempt to save will certainly not complain of a discrepancy. */)
5386 (void)
5387{
5388 current_buffer->modtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS);
5389 current_buffer->modtime_size = -1;
5390 return Qnil;
5391}
5392
5393DEFUN ("visited-file-modtime", Fvisited_file_modtime, 5377DEFUN ("visited-file-modtime", Fvisited_file_modtime,
5394 Svisited_file_modtime, 0, 0, 0, 5378 Svisited_file_modtime, 0, 0, 0,
5395 doc: /* Return the current buffer's recorded visited file modification time. 5379 doc: /* Return the current buffer's recorded visited file modification time.
5396The value is a list of the form (HIGH LOW USEC PSEC), like the time values that 5380The value is a list of the form (HIGH LOW USEC PSEC), like the time values that
5397`file-attributes' returns. If the current buffer has no recorded file 5381`file-attributes' returns. If the current buffer has no recorded file
5398modification time, this function returns 0. If the visited file 5382modification time, this function returns 0. If the visited file
5399doesn't exist, HIGH will be -1. 5383doesn't exist, return -1.
5400See Info node `(elisp)Modification Time' for more details. */) 5384See Info node `(elisp)Modification Time' for more details. */)
5401 (void) 5385 (void)
5402{ 5386{
5403 if (EMACS_NSECS (current_buffer->modtime) < 0) 5387 int ns = EMACS_NSECS (current_buffer->modtime);
5404 { 5388 if (ns < 0)
5405 if (EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS) 5389 return make_number (UNKNOWN_MODTIME_NSECS - ns);
5406 {
5407 /* make_lisp_time won't work here if time_t is unsigned. */
5408 return list4i (-1, 65535, 0, 0);
5409 }
5410 return make_number (0);
5411 }
5412 return make_lisp_time (current_buffer->modtime); 5390 return make_lisp_time (current_buffer->modtime);
5413} 5391}
5414 5392
@@ -5419,12 +5397,22 @@ Useful if the buffer was not read from the file normally
5419or if the file itself has been changed for some known benign reason. 5397or if the file itself has been changed for some known benign reason.
5420An argument specifies the modification time value to use 5398An argument specifies the modification time value to use
5421\(instead of that of the visited file), in the form of a list 5399\(instead of that of the visited file), in the form of a list
5422\(HIGH LOW USEC PSEC) as returned by `current-time'. */) 5400\(HIGH LOW USEC PSEC) or an integer flag as returned by
5423 (Lisp_Object time_list) 5401`visited-file-modtime'. */)
5402 (Lisp_Object time_flag)
5424{ 5403{
5425 if (!NILP (time_list)) 5404 if (!NILP (time_flag))
5426 { 5405 {
5427 current_buffer->modtime = lisp_time_argument (time_list); 5406 EMACS_TIME mtime;
5407 if (INTEGERP (time_flag))
5408 {
5409 CHECK_RANGED_INTEGER (time_flag, -1, 0);
5410 mtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS - XINT (time_flag));
5411 }
5412 else
5413 mtime = lisp_time_argument (time_flag);
5414
5415 current_buffer->modtime = mtime;
5428 current_buffer->modtime_size = -1; 5416 current_buffer->modtime_size = -1;
5429 } 5417 }
5430 else 5418 else
@@ -5620,7 +5608,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
5620 UNGCPRO; 5608 UNGCPRO;
5621 } 5609 }
5622 5610
5623 stream = fopen (SSDATA (listfile), "w"); 5611 stream = emacs_fopen (SSDATA (listfile), "w");
5624 } 5612 }
5625 5613
5626 record_unwind_protect (do_auto_save_unwind, 5614 record_unwind_protect (do_auto_save_unwind,
@@ -5887,6 +5875,7 @@ syms_of_fileio (void)
5887 DEFSYM (Qfile_error, "file-error"); 5875 DEFSYM (Qfile_error, "file-error");
5888 DEFSYM (Qfile_already_exists, "file-already-exists"); 5876 DEFSYM (Qfile_already_exists, "file-already-exists");
5889 DEFSYM (Qfile_date_error, "file-date-error"); 5877 DEFSYM (Qfile_date_error, "file-date-error");
5878 DEFSYM (Qfile_notify_error, "file-notify-error");
5890 DEFSYM (Qexcl, "excl"); 5879 DEFSYM (Qexcl, "excl");
5891 5880
5892 DEFVAR_LISP ("file-name-coding-system", Vfile_name_coding_system, 5881 DEFVAR_LISP ("file-name-coding-system", Vfile_name_coding_system,
@@ -5925,6 +5914,11 @@ of file names regardless of the current language environment. */);
5925 Fput (Qfile_date_error, Qerror_message, 5914 Fput (Qfile_date_error, Qerror_message,
5926 build_pure_c_string ("Cannot set file date")); 5915 build_pure_c_string ("Cannot set file date"));
5927 5916
5917 Fput (Qfile_notify_error, Qerror_conditions,
5918 Fpurecopy (list3 (Qfile_notify_error, Qfile_error, Qerror)));
5919 Fput (Qfile_notify_error, Qerror_message,
5920 build_pure_c_string ("File notification error"));
5921
5928 DEFVAR_LISP ("file-name-handler-alist", Vfile_name_handler_alist, 5922 DEFVAR_LISP ("file-name-handler-alist", Vfile_name_handler_alist,
5929 doc: /* Alist of elements (REGEXP . HANDLER) for file names handled specially. 5923 doc: /* Alist of elements (REGEXP . HANDLER) for file names handled specially.
5930If a file name matches REGEXP, all I/O on that file is done by calling 5924If a file name matches REGEXP, all I/O on that file is done by calling
@@ -6119,7 +6113,6 @@ This includes interactive calls to `delete-file' and
6119 defsubr (&Swrite_region); 6113 defsubr (&Swrite_region);
6120 defsubr (&Scar_less_than_car); 6114 defsubr (&Scar_less_than_car);
6121 defsubr (&Sverify_visited_file_modtime); 6115 defsubr (&Sverify_visited_file_modtime);
6122 defsubr (&Sclear_visited_file_modtime);
6123 defsubr (&Svisited_file_modtime); 6116 defsubr (&Svisited_file_modtime);
6124 defsubr (&Sset_visited_file_modtime); 6117 defsubr (&Sset_visited_file_modtime);
6125 defsubr (&Sdo_auto_save); 6118 defsubr (&Sdo_auto_save);
diff --git a/src/filelock.c b/src/filelock.c
index de6aba8385c..244663ad20a 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -47,6 +47,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
47#include "systime.h" 47#include "systime.h"
48#ifdef WINDOWSNT 48#ifdef WINDOWSNT
49#include <share.h> 49#include <share.h>
50#include <sys/socket.h> /* for fcntl */
50#include "w32.h" /* for dostounix_filename */ 51#include "w32.h" /* for dostounix_filename */
51#endif 52#endif
52 53
@@ -380,9 +381,9 @@ rename_lock_file (char const *old, char const *new, bool force)
380#endif 381#endif
381} 382}
382 383
383/* Create the lock file FILE with contents CONTENTS. Return 0 if 384/* Create the lock file LFNAME with contents LOCK_INFO_STR. Return 0 if
384 successful, an errno value on failure. If FORCE, remove any 385 successful, an errno value on failure. If FORCE, remove any
385 existing FILE if necessary. */ 386 existing LFNAME if necessary. */
386 387
387static int 388static int
388create_lock_file (char *lfname, char *lock_info_str, bool force) 389create_lock_file (char *lfname, char *lock_info_str, bool force)
@@ -416,8 +417,13 @@ create_lock_file (char *lfname, char *lock_info_str, bool force)
416 memcpy (nonce, lfname, lfdirlen); 417 memcpy (nonce, lfname, lfdirlen);
417 strcpy (nonce + lfdirlen, nonce_base); 418 strcpy (nonce + lfdirlen, nonce_base);
418 419
419#if HAVE_MKSTEMP 420#if HAVE_MKOSTEMP
420 /* Prefer mkstemp if available, as it avoids a race between 421 /* Prefer mkostemp to mkstemp, as it avoids a window where FD is
422 temporarily open without close-on-exec. */
423 fd = mkostemp (nonce, O_BINARY | O_CLOEXEC);
424 need_fchmod = 1;
425#elif HAVE_MKSTEMP
426 /* Prefer mkstemp to mktemp, as it avoids a race between
421 mktemp and emacs_open. */ 427 mktemp and emacs_open. */
422 fd = mkstemp (nonce); 428 fd = mkstemp (nonce);
423 need_fchmod = 1; 429 need_fchmod = 1;
@@ -432,7 +438,11 @@ create_lock_file (char *lfname, char *lock_info_str, bool force)
432 err = errno; 438 err = errno;
433 else 439 else
434 { 440 {
435 ptrdiff_t lock_info_len = strlen (lock_info_str); 441 ptrdiff_t lock_info_len;
442#if ! HAVE_MKOSTEMP
443 fcntl (fd, F_SETFD, FD_CLOEXEC);
444#endif
445 lock_info_len = strlen (lock_info_str);
436 err = 0; 446 err = 0;
437 if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len 447 if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len
438 || (need_fchmod && fchmod (fd, world_readable) != 0)) 448 || (need_fchmod && fchmod (fd, world_readable) != 0))
diff --git a/src/fns.c b/src/fns.c
index 7a8ddc04540..49bd8470f7f 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -5011,13 +5011,21 @@ this variable. */);
5011 defsubr (&Ssecure_hash); 5011 defsubr (&Ssecure_hash);
5012 defsubr (&Slocale_info); 5012 defsubr (&Slocale_info);
5013 5013
5014 { 5014 hashtest_eq.name = Qeq;
5015 struct hash_table_test 5015 hashtest_eq.user_hash_function = Qnil;
5016 eq = { Qeq, Qnil, Qnil, NULL, hashfn_eq }, 5016 hashtest_eq.user_cmp_function = Qnil;
5017 eql = { Qeql, Qnil, Qnil, cmpfn_eql, hashfn_eql }, 5017 hashtest_eq.cmpfn = 0;
5018 equal = { Qequal, Qnil, Qnil, cmpfn_equal, hashfn_equal }; 5018 hashtest_eq.hashfn = hashfn_eq;
5019 hashtest_eq = eq; 5019
5020 hashtest_eql = eql; 5020 hashtest_eql.name = Qeql;
5021 hashtest_equal = equal; 5021 hashtest_eql.user_hash_function = Qnil;
5022 } 5022 hashtest_eql.user_cmp_function = Qnil;
5023 hashtest_eql.cmpfn = cmpfn_eql;
5024 hashtest_eql.hashfn = hashfn_eql;
5025
5026 hashtest_equal.name = Qequal;
5027 hashtest_equal.user_hash_function = Qnil;
5028 hashtest_equal.user_cmp_function = Qnil;
5029 hashtest_equal.cmpfn = cmpfn_equal;
5030 hashtest_equal.hashfn = hashfn_equal;
5023} 5031}
diff --git a/src/frame.c b/src/frame.c
index ba9074ddebe..648687a7cb4 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1855,7 +1855,7 @@ See `redirect-frame-focus'. */)
1855/* Return the value of frame parameter PROP in frame FRAME. */ 1855/* Return the value of frame parameter PROP in frame FRAME. */
1856 1856
1857#ifdef HAVE_WINDOW_SYSTEM 1857#ifdef HAVE_WINDOW_SYSTEM
1858#if !HAVE_NS && !defined(WINDOWSNT) 1858#if !HAVE_NS && !defined (WINDOWSNT)
1859static 1859static
1860#endif 1860#endif
1861Lisp_Object 1861Lisp_Object
@@ -2964,6 +2964,15 @@ x_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
2964 f->extra_line_spacing = 0; 2964 f->extra_line_spacing = 0;
2965 else if (RANGED_INTEGERP (0, new_value, INT_MAX)) 2965 else if (RANGED_INTEGERP (0, new_value, INT_MAX))
2966 f->extra_line_spacing = XFASTINT (new_value); 2966 f->extra_line_spacing = XFASTINT (new_value);
2967 else if (FLOATP (new_value))
2968 {
2969 int new_spacing = XFLOAT_DATA (new_value) * FRAME_LINE_HEIGHT (f) + 0.5;
2970
2971 if (new_spacing >= 0)
2972 f->extra_line_spacing = new_spacing;
2973 else
2974 signal_error ("Invalid line-spacing", new_value);
2975 }
2967 else 2976 else
2968 signal_error ("Invalid line-spacing", new_value); 2977 signal_error ("Invalid line-spacing", new_value);
2969 if (FRAME_VISIBLE_P (f)) 2978 if (FRAME_VISIBLE_P (f))
diff --git a/src/gfilenotify.c b/src/gfilenotify.c
index c8d12ce8fa0..4e684d1fb54 100644
--- a/src/gfilenotify.c
+++ b/src/gfilenotify.c
@@ -132,15 +132,14 @@ This arranges for filesystem events pertaining to FILE to be reported
132to Emacs. Use `gfile-rm-watch' to cancel the watch. 132to Emacs. Use `gfile-rm-watch' to cancel the watch.
133 133
134Value is a descriptor for the added watch. If the file cannot be 134Value is a descriptor for the added watch. If the file cannot be
135watched for some reason, this function signals a `file-error' error. 135watched for some reason, this function signals a `file-notify-error' error.
136 136
137FLAGS is a list of conditions to set what will be watched for. It can 137FLAGS is a list of conditions to set what will be watched for. It can
138include the following symbols: 138include the following symbols:
139 139
140 'watch-mounts' -- watch for mount events 140 'watch-mounts' -- watch for mount events
141 'send-moved' -- pair 'deleted' and 'created' events caused by file 141 'send-moved' -- pair 'deleted' and 'created' events caused by file
142 renames (moves) and send a single 'event-moved' 142 renames and send a single 'renamed' event instead
143 event instead
144 143
145When any event happens, Emacs will call the CALLBACK function passing 144When any event happens, Emacs will call the CALLBACK function passing
146it a single argument EVENT, which is of the form 145it a single argument EVENT, which is of the form
@@ -193,7 +192,7 @@ will be reported only in case of the 'moved' event. */)
193 /* Enable watch. */ 192 /* Enable watch. */
194 monitor = g_file_monitor (gfile, gflags, NULL, NULL); 193 monitor = g_file_monitor (gfile, gflags, NULL, NULL);
195 if (! monitor) 194 if (! monitor)
196 xsignal2 (Qfile_error, build_string ("Cannot watch file"), file); 195 xsignal2 (Qfile_notify_error, build_string ("Cannot watch file"), file);
197 196
198 /* On all known glib platforms, converting MONITOR directly to a 197 /* On all known glib platforms, converting MONITOR directly to a
199 Lisp_Object value results is a Lisp integer, which is safe. This 198 Lisp_Object value results is a Lisp integer, which is safe. This
@@ -202,7 +201,8 @@ will be reported only in case of the 'moved' event. */)
202 if (! INTEGERP (watch_descriptor)) 201 if (! INTEGERP (watch_descriptor))
203 { 202 {
204 g_object_unref (monitor); 203 g_object_unref (monitor);
205 xsignal2 (Qfile_error, build_string ("Unsupported file watcher"), file); 204 xsignal2 (Qfile_notify_error, build_string ("Unsupported file watcher"),
205 file);
206 } 206 }
207 207
208 g_signal_connect (monitor, "changed", 208 g_signal_connect (monitor, "changed",
@@ -226,14 +226,14 @@ WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'. */)
226 Lisp_Object watch_object = assq_no_quit (watch_descriptor, watch_list); 226 Lisp_Object watch_object = assq_no_quit (watch_descriptor, watch_list);
227 227
228 if (! CONSP (watch_object)) 228 if (! CONSP (watch_object))
229 xsignal2 (Qfile_error, build_string ("Not a watch descriptor"), 229 xsignal2 (Qfile_notify_error, build_string ("Not a watch descriptor"),
230 watch_descriptor); 230 watch_descriptor);
231 231
232 eassert (INTEGERP (watch_descriptor)); 232 eassert (INTEGERP (watch_descriptor));
233 int_monitor = XLI (watch_descriptor); 233 int_monitor = XLI (watch_descriptor);
234 monitor = (GFileMonitor *) int_monitor; 234 monitor = (GFileMonitor *) int_monitor;
235 if (!g_file_monitor_cancel (monitor)) 235 if (!g_file_monitor_cancel (monitor))
236 xsignal2 (Qfile_error, build_string ("Could not rm watch"), 236 xsignal2 (Qfile_notify_error, build_string ("Could not rm watch"),
237 watch_descriptor); 237 watch_descriptor);
238 238
239 /* Remove watch descriptor from watch list. */ 239 /* Remove watch descriptor from watch list. */
diff --git a/src/gnutls.h b/src/gnutls.h
index f1a337e7b3e..86dcab77b62 100644
--- a/src/gnutls.h
+++ b/src/gnutls.h
@@ -42,7 +42,7 @@ typedef enum
42 GNUTLS_STAGE_TRANSPORT_POINTERS_SET, 42 GNUTLS_STAGE_TRANSPORT_POINTERS_SET,
43 GNUTLS_STAGE_HANDSHAKE_TRIED, 43 GNUTLS_STAGE_HANDSHAKE_TRIED,
44 44
45 GNUTLS_STAGE_READY, 45 GNUTLS_STAGE_READY
46} gnutls_initstage_t; 46} gnutls_initstage_t;
47 47
48#define GNUTLS_EMACS_ERROR_NOT_LOADED GNUTLS_E_APPLICATION_ERROR_MIN + 1 48#define GNUTLS_EMACS_ERROR_NOT_LOADED GNUTLS_E_APPLICATION_ERROR_MIN + 1
diff --git a/src/image.c b/src/image.c
index 2c288342028..c085e6e63eb 100644
--- a/src/image.c
+++ b/src/image.c
@@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19 19
20#include <config.h> 20#include <config.h>
21#include <stdio.h> 21#include "sysstdio.h"
22#include <unistd.h> 22#include <unistd.h>
23 23
24#ifdef HAVE_PNG 24#ifdef HAVE_PNG
@@ -316,7 +316,6 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
316 int xhot, yhot, result; 316 int xhot, yhot, result;
317 ptrdiff_t id; 317 ptrdiff_t id;
318 Lisp_Object found; 318 Lisp_Object found;
319 int fd;
320 char *filename; 319 char *filename;
321 320
322 /* Look for an existing bitmap with the same name. */ 321 /* Look for an existing bitmap with the same name. */
@@ -332,10 +331,8 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
332 } 331 }
333 332
334 /* Search bitmap-file-path for the file, if appropriate. */ 333 /* Search bitmap-file-path for the file, if appropriate. */
335 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil); 334 if (openp (Vx_bitmap_file_path, file, Qnil, &found, make_number (R_OK)) < 0)
336 if (fd < 0)
337 return -1; 335 return -1;
338 emacs_close (fd);
339 336
340 filename = SSDATA (found); 337 filename = SSDATA (found);
341 338
@@ -2260,7 +2257,8 @@ x_find_image_file (Lisp_Object file)
2260 else 2257 else
2261 { 2258 {
2262 file_found = ENCODE_FILE (file_found); 2259 file_found = ENCODE_FILE (file_found);
2263 close (fd); 2260 if (fd != -2)
2261 emacs_close (fd);
2264 } 2262 }
2265 2263
2266 return file_found; 2264 return file_found;
@@ -2274,7 +2272,7 @@ x_find_image_file (Lisp_Object file)
2274static unsigned char * 2272static unsigned char *
2275slurp_file (char *file, ptrdiff_t *size) 2273slurp_file (char *file, ptrdiff_t *size)
2276{ 2274{
2277 FILE *fp = fopen (file, "rb"); 2275 FILE *fp = emacs_fopen (file, "rb");
2278 unsigned char *buf = NULL; 2276 unsigned char *buf = NULL;
2279 struct stat st; 2277 struct stat st;
2280 2278
@@ -4559,7 +4557,6 @@ x_to_xcolors (struct frame *f, struct image *img, bool rgb_p)
4559 XColor *colors, *p; 4557 XColor *colors, *p;
4560 XImagePtr_or_DC ximg; 4558 XImagePtr_or_DC ximg;
4561#ifdef HAVE_NTGUI 4559#ifdef HAVE_NTGUI
4562 HDC hdc;
4563 HGDIOBJ prev; 4560 HGDIOBJ prev;
4564#endif /* HAVE_NTGUI */ 4561#endif /* HAVE_NTGUI */
4565 4562
@@ -4929,7 +4926,6 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
4929#ifndef HAVE_NTGUI 4926#ifndef HAVE_NTGUI
4930 XImagePtr mask_img; 4927 XImagePtr mask_img;
4931#else 4928#else
4932 HDC frame_dc;
4933 HGDIOBJ prev; 4929 HGDIOBJ prev;
4934 char *mask_img; 4930 char *mask_img;
4935 int row_width; 4931 int row_width;
@@ -5725,7 +5721,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5725 } 5721 }
5726 5722
5727 /* Open the image file. */ 5723 /* Open the image file. */
5728 fp = fopen (SSDATA (file), "rb"); 5724 fp = emacs_fopen (SSDATA (file), "rb");
5729 if (!fp) 5725 if (!fp)
5730 { 5726 {
5731 image_error ("Cannot open image file `%s'", file, Qnil); 5727 image_error ("Cannot open image file `%s'", file, Qnil);
@@ -6486,7 +6482,7 @@ jpeg_load_body (struct frame *f, struct image *img,
6486 return 0; 6482 return 0;
6487 } 6483 }
6488 6484
6489 fp = fopen (SSDATA (file), "rb"); 6485 fp = emacs_fopen (SSDATA (file), "rb");
6490 if (fp == NULL) 6486 if (fp == NULL)
6491 { 6487 {
6492 image_error ("Cannot open `%s'", file, Qnil); 6488 image_error ("Cannot open `%s'", file, Qnil);
@@ -7627,6 +7623,31 @@ gif_load (struct frame *f, struct image *img)
7627#endif /* HAVE_GIF */ 7623#endif /* HAVE_GIF */
7628 7624
7629 7625
7626#ifdef HAVE_IMAGEMAGICK
7627
7628/***********************************************************************
7629 ImageMagick
7630***********************************************************************/
7631
7632/* Scale an image size by returning SIZE / DIVISOR * MULTIPLIER,
7633 safely rounded and clipped to int range. */
7634
7635static int
7636scale_image_size (int size, size_t divisor, size_t multiplier)
7637{
7638 if (divisor != 0)
7639 {
7640 double s = size;
7641 double scaled = s * multiplier / divisor + 0.5;
7642 if (scaled < INT_MAX)
7643 return scaled;
7644 }
7645 return INT_MAX;
7646}
7647
7648/* Compute the desired size of an image with native size WIDTH x HEIGHT.
7649 Use SPEC to deduce the size. Store the desired size into
7650 *D_WIDTH x *D_HEIGHT. Store -1 x -1 if the native size is OK. */
7630static void 7651static void
7631compute_image_size (size_t width, size_t height, 7652compute_image_size (size_t width, size_t height,
7632 Lisp_Object spec, 7653 Lisp_Object spec,
@@ -7640,39 +7661,36 @@ compute_image_size (size_t width, size_t height,
7640 unspecified should be calculated from the specified to preserve 7661 unspecified should be calculated from the specified to preserve
7641 aspect ratio. */ 7662 aspect ratio. */
7642 value = image_spec_value (spec, QCwidth, NULL); 7663 value = image_spec_value (spec, QCwidth, NULL);
7643 desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); 7664 desired_width = NATNUMP (value) ? min (XFASTINT (value), INT_MAX) : -1;
7644 value = image_spec_value (spec, QCheight, NULL); 7665 value = image_spec_value (spec, QCheight, NULL);
7645 desired_height = (INTEGERP (value) ? XFASTINT (value) : -1); 7666 desired_height = NATNUMP (value) ? min (XFASTINT (value), INT_MAX) : -1;
7646 7667
7647 if (desired_width == -1) 7668 if (desired_width == -1)
7648 { 7669 {
7649 value = image_spec_value (spec, QCmax_width, NULL); 7670 value = image_spec_value (spec, QCmax_width, NULL);
7650 if (INTEGERP (value) && 7671 if (NATNUMP (value))
7651 width > XFASTINT (value))
7652 { 7672 {
7653 /* The image is wider than :max-width. */ 7673 int max_width = min (XFASTINT (value), INT_MAX);
7654 desired_width = XFASTINT (value); 7674 if (max_width < width)
7655 if (desired_height == -1)
7656 { 7675 {
7657 value = image_spec_value (spec, QCmax_height, NULL); 7676 /* The image is wider than :max-width. */
7658 if (INTEGERP (value)) 7677 desired_width = max_width;
7678 if (desired_height == -1)
7659 { 7679 {
7660 /* We have no specified height, but we have a 7680 desired_height = scale_image_size (desired_width,
7661 :max-height value, so check that we satisfy both 7681 width, height);
7662 conditions. */ 7682 value = image_spec_value (spec, QCmax_height, NULL);
7663 desired_height = (double) desired_width / width * height; 7683 if (NATNUMP (value))
7664 if (desired_height > XFASTINT (value))
7665 { 7684 {
7666 desired_height = XFASTINT (value); 7685 int max_height = min (XFASTINT (value), INT_MAX);
7667 desired_width = (double) desired_height / height * width; 7686 if (max_height < desired_height)
7687 {
7688 desired_height = max_height;
7689 desired_width = scale_image_size (desired_height,
7690 height, width);
7691 }
7668 } 7692 }
7669 } 7693 }
7670 else
7671 {
7672 /* We have no specified height and no specified
7673 max-height, so just compute the height. */
7674 desired_height = (double) desired_width / width * height;
7675 }
7676 } 7694 }
7677 } 7695 }
7678 } 7696 }
@@ -7680,28 +7698,26 @@ compute_image_size (size_t width, size_t height,
7680 if (desired_height == -1) 7698 if (desired_height == -1)
7681 { 7699 {
7682 value = image_spec_value (spec, QCmax_height, NULL); 7700 value = image_spec_value (spec, QCmax_height, NULL);
7683 if (INTEGERP (value) && 7701 if (NATNUMP (value))
7684 height > XFASTINT (value)) 7702 {
7685 desired_height = XFASTINT (value); 7703 int max_height = min (XFASTINT (value), INT_MAX);
7704 if (max_height < height)
7705 desired_height = max_height;
7706 }
7686 } 7707 }
7687 7708
7688 if (desired_width != -1 && desired_height == -1) 7709 if (desired_width != -1 && desired_height == -1)
7689 /* w known, calculate h. */ 7710 /* w known, calculate h. */
7690 desired_height = (double) desired_width / width * height; 7711 desired_height = scale_image_size (desired_width, width, height);
7691 7712
7692 if (desired_width == -1 && desired_height != -1) 7713 if (desired_width == -1 && desired_height != -1)
7693 /* h known, calculate w. */ 7714 /* h known, calculate w. */
7694 desired_width = (double) desired_height / height * width; 7715 desired_width = scale_image_size (desired_height, height, width);
7695 7716
7696 *d_width = desired_width; 7717 *d_width = desired_width;
7697 *d_height = desired_height; 7718 *d_height = desired_height;
7698} 7719}
7699 7720
7700/***********************************************************************
7701 ImageMagick
7702***********************************************************************/
7703#if defined (HAVE_IMAGEMAGICK)
7704
7705static Lisp_Object Qimagemagick; 7721static Lisp_Object Qimagemagick;
7706 7722
7707static bool imagemagick_image_p (Lisp_Object); 7723static bool imagemagick_image_p (Lisp_Object);
@@ -8036,7 +8052,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
8036 8052
8037 init_color_table (); 8053 init_color_table ();
8038 8054
8039#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS 8055#if defined (HAVE_MAGICKEXPORTIMAGEPIXELS) && ! defined (HAVE_NS)
8040 if (imagemagick_render_type != 0) 8056 if (imagemagick_render_type != 0)
8041 { 8057 {
8042 /* Magicexportimage is normally faster than pixelpushing. This 8058 /* Magicexportimage is normally faster than pixelpushing. This
diff --git a/src/inotify.c b/src/inotify.c
index 4efef9e55b7..f4f850bf180 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -71,9 +71,8 @@ static Lisp_Object Qunmount; /* IN_UNMOUNT */
71# define IN_ONLYDIR 0 71# define IN_ONLYDIR 0
72#endif 72#endif
73 73
74enum { uninitialized = -100 };
75/* File handle for inotify. */ 74/* File handle for inotify. */
76static int inotifyfd = uninitialized; 75static int inotifyfd = -1;
77 76
78/* Assoc list of files being watched. 77/* Assoc list of files being watched.
79 Format: 78 Format:
@@ -139,8 +138,8 @@ inotifyevent_to_event (Lisp_Object watch_object, struct inotify_event const *ev)
139 138
140 return list2 (list4 (make_watch_descriptor (ev->wd), 139 return list2 (list4 (make_watch_descriptor (ev->wd),
141 mask_to_aspects (ev->mask), 140 mask_to_aspects (ev->mask),
142 make_number (ev->cookie), 141 name,
143 name), 142 make_number (ev->cookie)),
144 XCDR (watch_object)); 143 XCDR (watch_object));
145} 144}
146 145
@@ -158,15 +157,17 @@ inotify_callback (int fd, void *_)
158 157
159 to_read = 0; 158 to_read = 0;
160 if (ioctl (fd, FIONREAD, &to_read) == -1) 159 if (ioctl (fd, FIONREAD, &to_read) == -1)
161 report_file_error ("Error while trying to retrieve file system events", 160 xsignal1
162 Qnil); 161 (Qfile_notify_error,
162 build_string ("Error while trying to retrieve file system events"));
163 buffer = xmalloc (to_read); 163 buffer = xmalloc (to_read);
164 n = read (fd, buffer, to_read); 164 n = read (fd, buffer, to_read);
165 if (n < 0) 165 if (n < 0)
166 { 166 {
167 xfree (buffer); 167 xfree (buffer);
168 report_file_error ("Error while trying to read file system events", 168 xsignal1
169 Qnil); 169 (Qfile_notify_error,
170 build_string ("Error while trying to read file system events"));
170 } 171 }
171 172
172 EVENT_INIT (event); 173 EVENT_INIT (event);
@@ -242,7 +243,7 @@ symbol_to_inotifymask (Lisp_Object symb)
242 else if (EQ (symb, Qt) || EQ (symb, Qall_events)) 243 else if (EQ (symb, Qt) || EQ (symb, Qall_events))
243 return IN_ALL_EVENTS; 244 return IN_ALL_EVENTS;
244 else 245 else
245 signal_error ("Unknown aspect", symb); 246 xsignal2 (Qfile_notify_error, build_string ("Unknown aspect"), symb);
246} 247}
247 248
248static uint32_t 249static uint32_t
@@ -266,8 +267,10 @@ aspect_to_inotifymask (Lisp_Object aspect)
266DEFUN ("inotify-add-watch", Finotify_add_watch, Sinotify_add_watch, 3, 3, 0, 267DEFUN ("inotify-add-watch", Finotify_add_watch, Sinotify_add_watch, 3, 3, 0,
267 doc: /* Add a watch for FILE-NAME to inotify. 268 doc: /* Add a watch for FILE-NAME to inotify.
268 269
269A WATCH-DESCRIPTOR is returned on success. ASPECT might be one of the following 270Return a watch descriptor. The watch will look for ASPECT events and
270symbols or a list of those symbols: 271invoke CALLBACK when an event occurs.
272
273ASPECT might be one of the following symbols or a list of those symbols:
271 274
272access 275access
273attrib 276attrib
@@ -286,7 +289,7 @@ all-events or t
286move 289move
287close 290close
288 291
289The following symbols can also be added to a list of aspects 292The following symbols can also be added to a list of aspects:
290 293
291dont-follow 294dont-follow
292excl-unlink 295excl-unlink
@@ -294,11 +297,10 @@ mask-add
294oneshot 297oneshot
295onlydir 298onlydir
296 299
297Watching a directory is not recursive. CALLBACK gets called in case of an 300Watching a directory is not recursive. CALLBACK is passed a single argument
298event. It gets passed a single argument EVENT which contains an event structure 301EVENT which contains an event structure of the format
299of the format
300 302
301(WATCH-DESCRIPTOR ASPECTS COOKIE NAME) 303(WATCH-DESCRIPTOR ASPECTS NAME COOKIE)
302 304
303WATCH-DESCRIPTOR is the same object that was returned by this function. It can 305WATCH-DESCRIPTOR is the same object that was returned by this function. It can
304be tested for equality using `equal'. ASPECTS describes the event. It is a 306be tested for equality using `equal'. ASPECTS describes the event. It is a
@@ -310,11 +312,11 @@ isdir
310q-overflow 312q-overflow
311unmount 313unmount
312 314
315If a directory is watched then NAME is the name of file that caused the event.
316
313COOKIE is an object that can be compared using `equal' to identify two matching 317COOKIE is an object that can be compared using `equal' to identify two matching
314renames (moved-from and moved-to). 318renames (moved-from and moved-to).
315 319
316If a directory is watched then NAME is the name of file that caused the event.
317
318See inotify(7) and inotify_add_watch(2) for further information. The inotify fd 320See inotify(7) and inotify_add_watch(2) for further information. The inotify fd
319is managed internally and there is no corresponding inotify_init. Use 321is managed internally and there is no corresponding inotify_init. Use
320`inotify-rm-watch' to remove a watch. 322`inotify-rm-watch' to remove a watch.
@@ -329,15 +331,13 @@ is managed internally and there is no corresponding inotify_init. Use
329 331
330 CHECK_STRING (file_name); 332 CHECK_STRING (file_name);
331 333
332 if (inotifyfd == uninitialized) 334 if (inotifyfd < 0)
333 { 335 {
334 inotifyfd = inotify_init1 (IN_NONBLOCK|IN_CLOEXEC); 336 inotifyfd = inotify_init1 (IN_NONBLOCK|IN_CLOEXEC);
335 if (inotifyfd == -1) 337 if (inotifyfd < 0)
336 { 338 xsignal1
337 inotifyfd = uninitialized; 339 (Qfile_notify_error,
338 report_file_error ("File watching feature (inotify) is not available", 340 build_string ("File watching feature (inotify) is not available"));
339 Qnil);
340 }
341 watch_list = Qnil; 341 watch_list = Qnil;
342 add_read_fd (inotifyfd, &inotify_callback, NULL); 342 add_read_fd (inotifyfd, &inotify_callback, NULL);
343 } 343 }
@@ -346,7 +346,8 @@ is managed internally and there is no corresponding inotify_init. Use
346 encoded_file_name = ENCODE_FILE (file_name); 346 encoded_file_name = ENCODE_FILE (file_name);
347 watchdesc = inotify_add_watch (inotifyfd, SSDATA (encoded_file_name), mask); 347 watchdesc = inotify_add_watch (inotifyfd, SSDATA (encoded_file_name), mask);
348 if (watchdesc == -1) 348 if (watchdesc == -1)
349 report_file_error ("Could not add watch for file", Fcons (file_name, Qnil)); 349 xsignal2 (Qfile_notify_error,
350 build_string ("Could not add watch for file"), file_name);
350 351
351 watch_descriptor = make_watch_descriptor (watchdesc); 352 watch_descriptor = make_watch_descriptor (watchdesc);
352 353
@@ -375,8 +376,8 @@ See inotify_rm_watch(2) for more information.
375 int wd = XINT (watch_descriptor); 376 int wd = XINT (watch_descriptor);
376 377
377 if (inotify_rm_watch (inotifyfd, wd) == -1) 378 if (inotify_rm_watch (inotifyfd, wd) == -1)
378 report_file_error ("Could not rm watch", Fcons (watch_descriptor, 379 xsignal2 (Qfile_notify_error,
379 Qnil)); 380 build_string ("Could not rm watch"), watch_descriptor);
380 381
381 /* Remove watch descriptor from watch list. */ 382 /* Remove watch descriptor from watch list. */
382 watch_object = Fassoc (watch_descriptor, watch_list); 383 watch_object = Fassoc (watch_descriptor, watch_list);
@@ -386,9 +387,9 @@ See inotify_rm_watch(2) for more information.
386 /* Cleanup if no more files are watched. */ 387 /* Cleanup if no more files are watched. */
387 if (NILP (watch_list)) 388 if (NILP (watch_list))
388 { 389 {
389 close (inotifyfd); 390 emacs_close (inotifyfd);
390 delete_read_fd (inotifyfd); 391 delete_read_fd (inotifyfd);
391 inotifyfd = uninitialized; 392 inotifyfd = -1;
392 } 393 }
393 394
394 return Qt; 395 return Qt;
diff --git a/src/keyboard.c b/src/keyboard.c
index 6129fdd26c8..a6f43d216ff 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -23,7 +23,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
23#define BLOCKINPUT_INLINE EXTERN_INLINE 23#define BLOCKINPUT_INLINE EXTERN_INLINE
24#define KEYBOARD_INLINE EXTERN_INLINE 24#define KEYBOARD_INLINE EXTERN_INLINE
25 25
26#include <stdio.h> 26#include "sysstdio.h"
27 27
28#include "lisp.h" 28#include "lisp.h"
29#include "termchar.h" 29#include "termchar.h"
@@ -2289,7 +2289,6 @@ read_event_from_main_queue (EMACS_TIME *end_time,
2289 XSETINT (c, XINT (c) | (extra_keyboard_modifiers & ~0xff7f & ~CHAR_CTL)); 2289 XSETINT (c, XINT (c) | (extra_keyboard_modifiers & ~0xff7f & ~CHAR_CTL));
2290 } 2290 }
2291 2291
2292 /* FIXME: Decode tty keyboard input here. */
2293 return c; 2292 return c;
2294} 2293}
2295 2294
@@ -7035,7 +7034,7 @@ tty_read_avail_input (struct terminal *terminal,
7035 { 7034 {
7036 nread = emacs_read (fileno (tty->input), (char *) cbuf, n_to_read); 7035 nread = emacs_read (fileno (tty->input), (char *) cbuf, n_to_read);
7037 /* POSIX infers that processes which are not in the session leader's 7036 /* POSIX infers that processes which are not in the session leader's
7038 process group won't get SIGHUP's at logout time. BSDI adheres to 7037 process group won't get SIGHUPs at logout time. BSDI adheres to
7039 this part standard and returns -1 from read (0) with errno==EIO 7038 this part standard and returns -1 from read (0) with errno==EIO
7040 when the control tty is taken away. 7039 when the control tty is taken away.
7041 Jeffrey Honig <jch@bsdi.com> says this is generally safe. */ 7040 Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
@@ -10156,7 +10155,7 @@ The file will be closed when Emacs exits. */)
10156 if (!NILP (file)) 10155 if (!NILP (file))
10157 { 10156 {
10158 file = Fexpand_file_name (file, Qnil); 10157 file = Fexpand_file_name (file, Qnil);
10159 dribble = fopen (SSDATA (file), "w"); 10158 dribble = emacs_fopen (SSDATA (file), "w");
10160 if (dribble == 0) 10159 if (dribble == 0)
10161 report_file_error ("Opening dribble", Fcons (file, Qnil)); 10160 report_file_error ("Opening dribble", Fcons (file, Qnil));
10162 } 10161 }
diff --git a/src/lisp.h b/src/lisp.h
index 6bea1ec67ed..e194a1ef765 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -363,9 +363,9 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 };
363#define INTMASK (EMACS_INT_MAX >> (INTTYPEBITS - 1)) 363#define INTMASK (EMACS_INT_MAX >> (INTTYPEBITS - 1))
364#define case_Lisp_Int case Lisp_Int0: case Lisp_Int1 364#define case_Lisp_Int case Lisp_Int0: case Lisp_Int1
365 365
366/* Idea stolen from GDB. MSVC doesn't support enums in bitfields, 366/* Idea stolen from GDB. Pedantic GCC complains about enum bitfields,
367 and xlc complains vociferously about them. */ 367 MSVC doesn't support them, and xlc complains vociferously about them. */
368#if defined _MSC_VER || defined __IBMC__ 368#if defined __STRICT_ANSI__ || defined _MSC_VER || defined __IBMC__
369#define ENUM_BF(TYPE) unsigned int 369#define ENUM_BF(TYPE) unsigned int
370#else 370#else
371#define ENUM_BF(TYPE) enum TYPE 371#define ENUM_BF(TYPE) enum TYPE
@@ -398,7 +398,7 @@ enum Lisp_Type
398 /* Cons. XCONS (object) points to a struct Lisp_Cons. */ 398 /* Cons. XCONS (object) points to a struct Lisp_Cons. */
399 Lisp_Cons = 6, 399 Lisp_Cons = 6,
400 400
401 Lisp_Float = 7, 401 Lisp_Float = 7
402 }; 402 };
403 403
404/* This is the set of data types that share a common structure. 404/* This is the set of data types that share a common structure.
@@ -428,7 +428,7 @@ enum Lisp_Fwd_Type
428 Lisp_Fwd_Bool, /* Fwd to a C boolean var. */ 428 Lisp_Fwd_Bool, /* Fwd to a C boolean var. */
429 Lisp_Fwd_Obj, /* Fwd to a C Lisp_Object variable. */ 429 Lisp_Fwd_Obj, /* Fwd to a C Lisp_Object variable. */
430 Lisp_Fwd_Buffer_Obj, /* Fwd to a Lisp_Object field of buffers. */ 430 Lisp_Fwd_Buffer_Obj, /* Fwd to a Lisp_Object field of buffers. */
431 Lisp_Fwd_Kboard_Obj, /* Fwd to a Lisp_Object field of kboards. */ 431 Lisp_Fwd_Kboard_Obj /* Fwd to a Lisp_Object field of kboards. */
432 }; 432 };
433 433
434/* If you want to define a new Lisp data type, here are some 434/* If you want to define a new Lisp data type, here are some
@@ -2545,11 +2545,16 @@ CHECK_NUMBER_CDR (Lisp_Object x)
2545 minargs, maxargs, lname, intspec, 0}; \ 2545 minargs, maxargs, lname, intspec, 0}; \
2546 Lisp_Object fnname 2546 Lisp_Object fnname
2547#else /* not _MSC_VER */ 2547#else /* not _MSC_VER */
2548# if __STDC_VERSION__ < 199901
2549# define DEFUN_FUNCTION_INIT(fnname, maxargs) (Lisp_Object (*) (void)) fnname
2550# else
2551# define DEFUN_FUNCTION_INIT(fnname, maxargs) .a ## maxargs = fnname
2552# endif
2548#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ 2553#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \
2549 Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ 2554 Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \
2550 static struct Lisp_Subr alignas (GCALIGNMENT) sname = \ 2555 static struct Lisp_Subr alignas (GCALIGNMENT) sname = \
2551 { { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \ 2556 { { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \
2552 { .a ## maxargs = fnname }, \ 2557 { DEFUN_FUNCTION_INIT (fnname, maxargs) }, \
2553 minargs, maxargs, lname, intspec, 0}; \ 2558 minargs, maxargs, lname, intspec, 0}; \
2554 Lisp_Object fnname 2559 Lisp_Object fnname
2555#endif 2560#endif
@@ -3673,7 +3678,6 @@ extern Lisp_Object string_to_number (char const *, int, bool);
3673extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object), 3678extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object),
3674 Lisp_Object); 3679 Lisp_Object);
3675extern void dir_warning (const char *, Lisp_Object); 3680extern void dir_warning (const char *, Lisp_Object);
3676extern void close_load_descs (void);
3677extern void init_obarray (void); 3681extern void init_obarray (void);
3678extern void init_lread (void); 3682extern void init_lread (void);
3679extern void syms_of_lread (void); 3683extern void syms_of_lread (void);
@@ -3814,6 +3818,7 @@ extern void syms_of_marker (void);
3814/* Defined in fileio.c. */ 3818/* Defined in fileio.c. */
3815 3819
3816extern Lisp_Object Qfile_error; 3820extern Lisp_Object Qfile_error;
3821extern Lisp_Object Qfile_notify_error;
3817extern Lisp_Object Qfile_exists_p; 3822extern Lisp_Object Qfile_exists_p;
3818extern Lisp_Object Qfile_directory_p; 3823extern Lisp_Object Qfile_directory_p;
3819extern Lisp_Object Qinsert_file_contents; 3824extern Lisp_Object Qinsert_file_contents;
@@ -3822,6 +3827,7 @@ extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object);
3822EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */ 3827EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */
3823extern Lisp_Object close_file_unwind (Lisp_Object); 3828extern Lisp_Object close_file_unwind (Lisp_Object);
3824extern Lisp_Object restore_point_unwind (Lisp_Object); 3829extern Lisp_Object restore_point_unwind (Lisp_Object);
3830extern _Noreturn void report_file_errno (const char *, Lisp_Object, int);
3825extern _Noreturn void report_file_error (const char *, Lisp_Object); 3831extern _Noreturn void report_file_error (const char *, Lisp_Object);
3826extern bool internal_delete_file (Lisp_Object); 3832extern bool internal_delete_file (Lisp_Object);
3827extern Lisp_Object emacs_readlinkat (int, const char *); 3833extern Lisp_Object emacs_readlinkat (int, const char *);
@@ -3927,7 +3933,7 @@ extern Lisp_Object Qvisible;
3927extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object); 3933extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object);
3928extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object); 3934extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object);
3929extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object); 3935extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object);
3930#if HAVE_NS || defined(WINDOWSNT) 3936#if HAVE_NS || defined WINDOWSNT
3931extern Lisp_Object get_frame_param (struct frame *, Lisp_Object); 3937extern Lisp_Object get_frame_param (struct frame *, Lisp_Object);
3932#endif 3938#endif
3933extern void frames_discard_buffer (Lisp_Object); 3939extern void frames_discard_buffer (Lisp_Object);
@@ -3999,11 +4005,11 @@ extern void delete_keyboard_wait_descriptor (int);
3999extern void add_gpm_wait_descriptor (int); 4005extern void add_gpm_wait_descriptor (int);
4000extern void delete_gpm_wait_descriptor (int); 4006extern void delete_gpm_wait_descriptor (int);
4001#endif 4007#endif
4002extern void close_process_descs (void);
4003extern void init_process_emacs (void); 4008extern void init_process_emacs (void);
4004extern void syms_of_process (void); 4009extern void syms_of_process (void);
4005extern void setup_process_coding_systems (Lisp_Object); 4010extern void setup_process_coding_systems (Lisp_Object);
4006 4011
4012/* Defined in callproc.c. */
4007#ifndef DOS_NT 4013#ifndef DOS_NT
4008 _Noreturn 4014 _Noreturn
4009#endif 4015#endif
@@ -4096,6 +4102,8 @@ extern int emacs_open (const char *, int, int);
4096extern int emacs_close (int); 4102extern int emacs_close (int);
4097extern ptrdiff_t emacs_read (int, char *, ptrdiff_t); 4103extern ptrdiff_t emacs_read (int, char *, ptrdiff_t);
4098extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t); 4104extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t);
4105extern ptrdiff_t emacs_write_sig (int, char const *, ptrdiff_t);
4106extern void emacs_perror (char const *);
4099 4107
4100extern void unlock_all_files (void); 4108extern void unlock_all_files (void);
4101extern void lock_file (Lisp_Object); 4109extern void lock_file (Lisp_Object);
diff --git a/src/lread.c b/src/lread.c
index b57665e365c..f0423f166dd 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -20,7 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 20
21 21
22#include <config.h> 22#include <config.h>
23#include <stdio.h> 23#include "sysstdio.h"
24#include <sys/types.h> 24#include <sys/types.h>
25#include <sys/stat.h> 25#include <sys/stat.h>
26#include <sys/file.h> 26#include <sys/file.h>
@@ -38,7 +38,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
38#include "keyboard.h" 38#include "keyboard.h"
39#include "frame.h" 39#include "frame.h"
40#include "termhooks.h" 40#include "termhooks.h"
41#include "coding.h"
42#include "blockinput.h" 41#include "blockinput.h"
43 42
44#ifdef MSDOS 43#ifdef MSDOS
@@ -96,9 +95,6 @@ static Lisp_Object Qload_in_progress;
96 It must be set to nil before all top-level calls to read0. */ 95 It must be set to nil before all top-level calls to read0. */
97static Lisp_Object read_objects; 96static Lisp_Object read_objects;
98 97
99/* List of descriptors now open for Fload. */
100static Lisp_Object load_descriptor_list;
101
102/* File for get_file_char to read from. Use by load. */ 98/* File for get_file_char to read from. Use by load. */
103static FILE *instream; 99static FILE *instream;
104 100
@@ -150,7 +146,6 @@ static void readevalloop (Lisp_Object, FILE *, Lisp_Object, bool,
150 Lisp_Object, Lisp_Object, 146 Lisp_Object, Lisp_Object,
151 Lisp_Object, Lisp_Object); 147 Lisp_Object, Lisp_Object);
152static Lisp_Object load_unwind (Lisp_Object); 148static Lisp_Object load_unwind (Lisp_Object);
153static Lisp_Object load_descriptor_unwind (Lisp_Object);
154 149
155/* Functions that read one byte from the current source READCHARFUN 150/* Functions that read one byte from the current source READCHARFUN
156 or unreads one byte. If the integer argument C is -1, it returns 151 or unreads one byte. If the integer argument C is -1, it returns
@@ -828,7 +823,7 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun)
828 { 823 {
829 bool rv = 0; 824 bool rv = 0;
830 enum { 825 enum {
831 NOMINAL, AFTER_FIRST_DASH, AFTER_ASTERIX, 826 NOMINAL, AFTER_FIRST_DASH, AFTER_ASTERIX
832 } beg_end_state = NOMINAL; 827 } beg_end_state = NOMINAL;
833 bool in_file_vars = 0; 828 bool in_file_vars = 0;
834 829
@@ -1298,7 +1293,7 @@ Return t if the file exists and loads successfully. */)
1298 if (fd >= 0) 1293 if (fd >= 0)
1299 { 1294 {
1300 emacs_close (fd); 1295 emacs_close (fd);
1301 stream = fopen (SSDATA (efound), fmode); 1296 stream = emacs_fopen (SSDATA (efound), fmode);
1302 } 1297 }
1303 else 1298 else
1304 stream = NULL; 1299 stream = NULL;
@@ -1329,11 +1324,8 @@ Return t if the file exists and loads successfully. */)
1329 } 1324 }
1330 1325
1331 record_unwind_protect (load_unwind, make_save_pointer (stream)); 1326 record_unwind_protect (load_unwind, make_save_pointer (stream));
1332 record_unwind_protect (load_descriptor_unwind, load_descriptor_list);
1333 specbind (Qload_file_name, found); 1327 specbind (Qload_file_name, found);
1334 specbind (Qinhibit_file_name_operation, Qnil); 1328 specbind (Qinhibit_file_name_operation, Qnil);
1335 load_descriptor_list
1336 = Fcons (make_number (fileno (stream)), load_descriptor_list);
1337 specbind (Qload_in_progress, Qt); 1329 specbind (Qload_in_progress, Qt);
1338 1330
1339 instream = stream; 1331 instream = stream;
@@ -1396,26 +1388,6 @@ load_unwind (Lisp_Object arg) /* Used as unwind-protect function in load. */
1396 } 1388 }
1397 return Qnil; 1389 return Qnil;
1398} 1390}
1399
1400static Lisp_Object
1401load_descriptor_unwind (Lisp_Object oldlist)
1402{
1403 load_descriptor_list = oldlist;
1404 return Qnil;
1405}
1406
1407/* Close all descriptors in use for Floads.
1408 This is used when starting a subprocess. */
1409
1410void
1411close_load_descs (void)
1412{
1413#ifndef WINDOWSNT
1414 Lisp_Object tail;
1415 for (tail = load_descriptor_list; CONSP (tail); tail = XCDR (tail))
1416 emacs_close (XFASTINT (XCAR (tail)));
1417#endif
1418}
1419 1391
1420static bool 1392static bool
1421complete_filename_p (Lisp_Object pathname) 1393complete_filename_p (Lisp_Object pathname)
@@ -1440,8 +1412,8 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */)
1440{ 1412{
1441 Lisp_Object file; 1413 Lisp_Object file;
1442 int fd = openp (path, filename, suffixes, &file, predicate); 1414 int fd = openp (path, filename, suffixes, &file, predicate);
1443 if (NILP (predicate) && fd > 0) 1415 if (NILP (predicate) && fd >= 0)
1444 close (fd); 1416 emacs_close (fd);
1445 return file; 1417 return file;
1446} 1418}
1447 1419
@@ -1449,14 +1421,15 @@ static Lisp_Object Qdir_ok;
1449 1421
1450/* Search for a file whose name is STR, looking in directories 1422/* Search for a file whose name is STR, looking in directories
1451 in the Lisp list PATH, and trying suffixes from SUFFIX. 1423 in the Lisp list PATH, and trying suffixes from SUFFIX.
1452 On success, returns a file descriptor. On failure, returns -1. 1424 On success, return a file descriptor (or 1 or -2 as described below).
1425 On failure, return -1 and set errno.
1453 1426
1454 SUFFIXES is a list of strings containing possible suffixes. 1427 SUFFIXES is a list of strings containing possible suffixes.
1455 The empty suffix is automatically added if the list is empty. 1428 The empty suffix is automatically added if the list is empty.
1456 1429
1457 PREDICATE non-nil means don't open the files, 1430 PREDICATE non-nil means don't open the files,
1458 just look for one that satisfies the predicate. In this case, 1431 just look for one that satisfies the predicate. In this case,
1459 returns 1 on success. The predicate can be a lisp function or 1432 return 1 on success. The predicate can be a lisp function or
1460 an integer to pass to `access' (in which case file-name-handlers 1433 an integer to pass to `access' (in which case file-name-handlers
1461 are ignored). 1434 are ignored).
1462 1435
@@ -1468,7 +1441,8 @@ static Lisp_Object Qdir_ok;
1468 but store the found remote file name in *STOREPTR. */ 1441 but store the found remote file name in *STOREPTR. */
1469 1442
1470int 1443int
1471openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *storeptr, Lisp_Object predicate) 1444openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
1445 Lisp_Object *storeptr, Lisp_Object predicate)
1472{ 1446{
1473 ptrdiff_t fn_size = 100; 1447 ptrdiff_t fn_size = 100;
1474 char buf[100]; 1448 char buf[100];
@@ -1479,6 +1453,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
1479 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6; 1453 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
1480 Lisp_Object string, tail, encoded_fn; 1454 Lisp_Object string, tail, encoded_fn;
1481 ptrdiff_t max_suffix_len = 0; 1455 ptrdiff_t max_suffix_len = 0;
1456 int last_errno = ENOENT;
1482 1457
1483 CHECK_STRING (str); 1458 CHECK_STRING (str);
1484 1459
@@ -1548,14 +1523,22 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
1548 if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate)) 1523 if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate))
1549 { 1524 {
1550 bool exists; 1525 bool exists;
1526 last_errno = ENOENT;
1551 if (NILP (predicate)) 1527 if (NILP (predicate))
1552 exists = !NILP (Ffile_readable_p (string)); 1528 exists = !NILP (Ffile_readable_p (string));
1553 else 1529 else
1554 { 1530 {
1555 Lisp_Object tmp = call1 (predicate, string); 1531 Lisp_Object tmp = call1 (predicate, string);
1556 exists = !NILP (tmp) 1532 if (NILP (tmp))
1557 && (EQ (tmp, Qdir_ok) 1533 exists = 0;
1558 || NILP (Ffile_directory_p (string))); 1534 else if (EQ (tmp, Qdir_ok)
1535 || NILP (Ffile_directory_p (string)))
1536 exists = 1;
1537 else
1538 {
1539 exists = 0;
1540 last_errno = EISDIR;
1541 }
1559 } 1542 }
1560 1543
1561 if (exists) 1544 if (exists)
@@ -1577,21 +1560,36 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
1577 1560
1578 /* Check that we can access or open it. */ 1561 /* Check that we can access or open it. */
1579 if (NATNUMP (predicate)) 1562 if (NATNUMP (predicate))
1580 fd = (((XFASTINT (predicate) & ~INT_MAX) == 0 1563 {
1581 && (faccessat (AT_FDCWD, pfn, XFASTINT (predicate), 1564 fd = -1;
1565 if (INT_MAX < XFASTINT (predicate))
1566 last_errno = EINVAL;
1567 else if (faccessat (AT_FDCWD, pfn, XFASTINT (predicate),
1582 AT_EACCESS) 1568 AT_EACCESS)
1583 == 0) 1569 == 0)
1584 && ! file_directory_p (pfn)) 1570 {
1585 ? 1 : -1); 1571 if (file_directory_p (pfn))
1572 last_errno = EISDIR;
1573 else
1574 fd = 1;
1575 }
1576 }
1586 else 1577 else
1587 { 1578 {
1588 struct stat st;
1589 fd = emacs_open (pfn, O_RDONLY, 0); 1579 fd = emacs_open (pfn, O_RDONLY, 0);
1590 if (fd >= 0 1580 if (fd < 0)
1591 && (fstat (fd, &st) != 0 || S_ISDIR (st.st_mode))) 1581 last_errno = errno;
1582 else
1592 { 1583 {
1593 emacs_close (fd); 1584 struct stat st;
1594 fd = -1; 1585 int err = (fstat (fd, &st) != 0 ? errno
1586 : S_ISDIR (st.st_mode) ? EISDIR : 0);
1587 if (err)
1588 {
1589 last_errno = err;
1590 emacs_close (fd);
1591 fd = -1;
1592 }
1595 } 1593 }
1596 } 1594 }
1597 1595
@@ -1610,6 +1608,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
1610 } 1608 }
1611 1609
1612 UNGCPRO; 1610 UNGCPRO;
1611 errno = last_errno;
1613 return -1; 1612 return -1;
1614} 1613}
1615 1614
@@ -4350,9 +4349,6 @@ init_lread (void)
4350 4349
4351 load_in_progress = 0; 4350 load_in_progress = 0;
4352 Vload_file_name = Qnil; 4351 Vload_file_name = Qnil;
4353
4354 load_descriptor_list = Qnil;
4355
4356 Vstandard_input = Qt; 4352 Vstandard_input = Qt;
4357 Vloads_in_progress = Qnil; 4353 Vloads_in_progress = Qnil;
4358} 4354}
@@ -4625,9 +4621,6 @@ variables, this must be set in the first line of a file. */);
4625 4621
4626 /* Vsource_directory was initialized in init_lread. */ 4622 /* Vsource_directory was initialized in init_lread. */
4627 4623
4628 load_descriptor_list = Qnil;
4629 staticpro (&load_descriptor_list);
4630
4631 DEFSYM (Qcurrent_load_list, "current-load-list"); 4624 DEFSYM (Qcurrent_load_list, "current-load-list");
4632 DEFSYM (Qstandard_input, "standard-input"); 4625 DEFSYM (Qstandard_input, "standard-input");
4633 DEFSYM (Qread_char, "read-char"); 4626 DEFSYM (Qread_char, "read-char");
diff --git a/src/makefile.w32-in b/src/makefile.w32-in
index 272b053ed12..f4885580e1c 100644
--- a/src/makefile.w32-in
+++ b/src/makefile.w32-in
@@ -813,7 +813,6 @@ $(BLD)/emacs.$(O) : \
813 $(NT_INC)/sys/file.h \ 813 $(NT_INC)/sys/file.h \
814 $(NT_INC)/unistd.h \ 814 $(NT_INC)/unistd.h \
815 $(GNU_LIB)/close-stream.h \ 815 $(GNU_LIB)/close-stream.h \
816 $(GNU_LIB)/ignore-value.h \
817 $(ATIMER_H) \ 816 $(ATIMER_H) \
818 $(BUFFER_H) \ 817 $(BUFFER_H) \
819 $(CHARACTER_H) \ 818 $(CHARACTER_H) \
@@ -1407,7 +1406,6 @@ $(BLD)/sysdep.$(O) : \
1407 $(NT_INC)/sys/stat.h \ 1406 $(NT_INC)/sys/stat.h \
1408 $(NT_INC)/unistd.h \ 1407 $(NT_INC)/unistd.h \
1409 $(GNU_LIB)/execinfo.h \ 1408 $(GNU_LIB)/execinfo.h \
1410 $(GNU_LIB)/ignore-value.h \
1411 $(GNU_LIB)/utimens.h \ 1409 $(GNU_LIB)/utimens.h \
1412 $(CONFIG_H) \ 1410 $(CONFIG_H) \
1413 $(C_CTYPE_H) \ 1411 $(C_CTYPE_H) \
diff --git a/src/nsfns.m b/src/nsfns.m
index 1e075995c11..6eebb4d2567 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -89,9 +89,6 @@ extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
89Lisp_Object Qbuffered; 89Lisp_Object Qbuffered;
90Lisp_Object Qfontsize; 90Lisp_Object Qfontsize;
91 91
92/* hack for OS X file panels */
93char panelOK = 0;
94
95EmacsTooltip *ns_tooltip = nil; 92EmacsTooltip *ns_tooltip = nil;
96 93
97/* Need forward declaration here to preserve organizational integrity of file */ 94/* Need forward declaration here to preserve organizational integrity of file */
@@ -888,7 +885,7 @@ ns_appkit_version_str (void)
888 885
889#ifdef NS_IMPL_GNUSTEP 886#ifdef NS_IMPL_GNUSTEP
890 sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION)); 887 sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION));
891#elif defined(NS_IMPL_COCOA) 888#elif defined (NS_IMPL_COCOA)
892 sprintf(tmp, "apple-appkit-%.2f", NSAppKitVersionNumber); 889 sprintf(tmp, "apple-appkit-%.2f", NSAppKitVersionNumber);
893#else 890#else
894 tmp = "ns-unknown"; 891 tmp = "ns-unknown";
@@ -905,7 +902,7 @@ ns_appkit_version_int (void)
905{ 902{
906#ifdef NS_IMPL_GNUSTEP 903#ifdef NS_IMPL_GNUSTEP
907 return GNUSTEP_GUI_MAJOR_VERSION * 100 + GNUSTEP_GUI_MINOR_VERSION; 904 return GNUSTEP_GUI_MAJOR_VERSION * 100 + GNUSTEP_GUI_MINOR_VERSION;
908#elif defined(NS_IMPL_COCOA) 905#elif defined (NS_IMPL_COCOA)
909 return (int)NSAppKitVersionNumber; 906 return (int)NSAppKitVersionNumber;
910#endif 907#endif
911 return 0; 908 return 0;
@@ -1396,6 +1393,41 @@ DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel,
1396 return Qnil; 1393 return Qnil;
1397} 1394}
1398 1395
1396static struct
1397{
1398 id panel;
1399 BOOL ret;
1400#if ! defined (NS_IMPL_COCOA) || \
1401 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
1402 NSString *dirS, *initS;
1403 BOOL no_types;
1404#endif
1405} ns_fd_data;
1406
1407void
1408ns_run_file_dialog (void)
1409{
1410 if (ns_fd_data.panel == nil) return;
1411#if defined (NS_IMPL_COCOA) && \
1412 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
1413 ns_fd_data.ret = [ns_fd_data.panel runModal];
1414#else
1415 if (ns_fd_data.no_types)
1416 {
1417 ns_fd_data.ret = [ns_fd_data.panel
1418 runModalForDirectory: ns_fd_data.dirS
1419 file: ns_fd_data.initS];
1420 }
1421 else
1422 {
1423 ns_fd_data.ret = [ns_fd_data.panel
1424 runModalForDirectory: ns_fd_data.dirS
1425 file: ns_fd_data.initS
1426 types: nil];
1427 }
1428#endif
1429 ns_fd_data.panel = nil;
1430}
1399 1431
1400DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 5, 0, 1432DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 5, 0,
1401 doc: /* Use a graphical panel to read a file name, using prompt PROMPT. 1433 doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
@@ -1420,6 +1452,7 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */)
1420 [NSString stringWithUTF8String: SSDATA (dir)]; 1452 [NSString stringWithUTF8String: SSDATA (dir)];
1421 NSString *initS = NILP (init) || !STRINGP (init) ? nil : 1453 NSString *initS = NILP (init) || !STRINGP (init) ? nil :
1422 [NSString stringWithUTF8String: SSDATA (init)]; 1454 [NSString stringWithUTF8String: SSDATA (init)];
1455 NSEvent *nxev;
1423 1456
1424 check_window_system (NULL); 1457 check_window_system (NULL);
1425 1458
@@ -1440,7 +1473,6 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */)
1440 [panel setTreatsFilePackagesAsDirectories: YES]; 1473 [panel setTreatsFilePackagesAsDirectories: YES];
1441 [panel setDelegate: fileDelegate]; 1474 [panel setDelegate: fileDelegate];
1442 1475
1443 panelOK = 0;
1444 if (! NILP (dir_only_p)) 1476 if (! NILP (dir_only_p))
1445 { 1477 {
1446 [panel setCanChooseDirectories: YES]; 1478 [panel setCanChooseDirectories: YES];
@@ -1454,7 +1486,9 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */)
1454 [panel setCanChooseFiles: YES]; 1486 [panel setCanChooseFiles: YES];
1455 } 1487 }
1456 1488
1457 block_input (); 1489 block_input ();
1490 ns_fd_data.panel = panel;
1491 ns_fd_data.ret = NO;
1458#if defined (NS_IMPL_COCOA) && \ 1492#if defined (NS_IMPL_COCOA) && \
1459 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 1493 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
1460 if (! NILP (mustmatch) || ! NILP (dir_only_p)) 1494 if (! NILP (mustmatch) || ! NILP (dir_only_p))
@@ -1465,19 +1499,32 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */)
1465 else 1499 else
1466 [panel setNameFieldStringValue: @""]; 1500 [panel setNameFieldStringValue: @""];
1467 1501
1468 ret = [panel runModal];
1469#else 1502#else
1470 if (NILP (mustmatch) && NILP (dir_only_p)) 1503 ns_fd_data.no_types = NILP (mustmatch) && NILP (dir_only_p);
1471 { 1504 ns_fd_data.dirS = dirS;
1472 ret = [panel runModalForDirectory: dirS file: initS]; 1505 ns_fd_data.initS = initS;
1473 }
1474 else
1475 {
1476 ret = [panel runModalForDirectory: dirS file: initS types: nil];
1477 }
1478#endif 1506#endif
1479 1507
1480 ret = (ret == NSOKButton) || panelOK; 1508 /* runModalForDirectory/runModal restarts the main event loop when done,
1509 so we must start an event loop and then pop up the file dialog.
1510 The file dialog may pop up a confirm dialog after Ok has been pressed,
1511 so we can not simply pop down on the Ok/Cancel press.
1512 */
1513 nxev = [NSEvent otherEventWithType: NSApplicationDefined
1514 location: NSMakePoint (0, 0)
1515 modifierFlags: 0
1516 timestamp: 0
1517 windowNumber: [[NSApp mainWindow] windowNumber]
1518 context: [NSApp context]
1519 subtype: 0
1520 data1: 0
1521 data2: NSAPP_DATA2_RUNFILEDIALOG];
1522
1523 [NSApp postEvent: nxev atStart: NO];
1524 while (ns_fd_data.panel != nil)
1525 [NSApp run];
1526
1527 ret = (ns_fd_data.ret == NSOKButton);
1481 1528
1482 if (ret) 1529 if (ret)
1483 { 1530 {
@@ -2446,7 +2493,7 @@ Internal use only, use `display-monitor-attributes-list' instead. */)
2446 vy = (short) (primary_display_height - 2493 vy = (short) (primary_display_height -
2447 vfr.size.height - vfr.origin.y); 2494 vfr.size.height - vfr.origin.y);
2448 } 2495 }
2449 2496
2450 m->geom.x = (short) fr.origin.x; 2497 m->geom.x = (short) fr.origin.x;
2451 m->geom.y = y; 2498 m->geom.y = y;
2452 m->geom.width = (unsigned short) fr.size.width; 2499 m->geom.width = (unsigned short) fr.size.width;
@@ -2755,25 +2802,6 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
2755} 2802}
2756 2803
2757@implementation EmacsSavePanel 2804@implementation EmacsSavePanel
2758#ifdef NS_IMPL_COCOA
2759/* --------------------------------------------------------------------------
2760 These are overridden to intercept on OS X: ending panel restarts NSApp
2761 event loop if it is stopped. Not sure if this is correct behavior,
2762 perhaps should check if running and if so send an appdefined.
2763 -------------------------------------------------------------------------- */
2764- (void) ok: (id)sender
2765{
2766 [super ok: sender];
2767 panelOK = 1;
2768 [NSApp stop: self];
2769}
2770- (void) cancel: (id)sender
2771{
2772 [super cancel: sender];
2773 [NSApp stop: self];
2774}
2775#endif
2776
2777- (BOOL)performKeyEquivalent:(NSEvent *)theEvent 2805- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
2778{ 2806{
2779 BOOL ret = handlePanelKeys (self, theEvent); 2807 BOOL ret = handlePanelKeys (self, theEvent);
@@ -2785,31 +2813,6 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
2785 2813
2786 2814
2787@implementation EmacsOpenPanel 2815@implementation EmacsOpenPanel
2788#ifdef NS_IMPL_COCOA
2789/* --------------------------------------------------------------------------
2790 These are overridden to intercept on OS X: ending panel restarts NSApp
2791 event loop if it is stopped. Not sure if this is correct behavior,
2792 perhaps should check if running and if so send an appdefined.
2793 -------------------------------------------------------------------------- */
2794- (void) ok: (id)sender
2795{
2796 [super ok: sender];
2797
2798 // If not choosing directories, and Open is pressed on a directory, return.
2799 if (! [self canChooseDirectories] && ns_directory_from_panel (self) &&
2800 ! ns_filename_from_panel (self))
2801 return;
2802
2803 panelOK = 1;
2804 [NSApp stop: self];
2805}
2806- (void) cancel: (id)sender
2807{
2808 [super cancel: sender];
2809 [NSApp stop: self];
2810}
2811
2812#endif
2813- (BOOL)performKeyEquivalent:(NSEvent *)theEvent 2816- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
2814{ 2817{
2815 // NSOpenPanel inherits NSSavePanel, so passing self is OK. 2818 // NSOpenPanel inherits NSSavePanel, so passing self is OK.
diff --git a/src/nsfont.m b/src/nsfont.m
index 49ede8f483c..a657d01dbe4 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -33,7 +33,6 @@ Author: Adrian Robert (arobert@cogsci.ucsd.edu)
33#include "window.h" 33#include "window.h"
34#include "fontset.h" 34#include "fontset.h"
35#include "nsterm.h" 35#include "nsterm.h"
36#include "frame.h"
37#include "character.h" 36#include "character.h"
38#include "font.h" 37#include "font.h"
39#include "termchar.h" 38#include "termchar.h"
diff --git a/src/nsmenu.m b/src/nsmenu.m
index 1d3d111e9a1..22635dca0a2 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -612,8 +612,8 @@ extern NSString *NSMenuDidBeginTrackingNotification;
612 if (trackingMenu == 0) 612 if (trackingMenu == 0)
613 return; 613 return;
614/*fprintf (stderr, "Updating menu '%s'\n", [[self title] UTF8String]); NSLog (@"%@\n", event); */ 614/*fprintf (stderr, "Updating menu '%s'\n", [[self title] UTF8String]); NSLog (@"%@\n", event); */
615#if ! defined(NS_IMPL_COCOA) || \ 615#if (! defined (NS_IMPL_COCOA) \
616 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 616 || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
617 /* Don't know how to do this for anything other than OSX >= 10.5 617 /* Don't know how to do this for anything other than OSX >= 10.5
618 This is wrong, as it might run Lisp code in the event loop. */ 618 This is wrong, as it might run Lisp code in the event loop. */
619 ns_update_menubar (frame, true, self); 619 ns_update_menubar (frame, true, self);
@@ -1240,7 +1240,7 @@ update_frame_tool_bar (FRAME_PTR f)
1240#ifdef NS_IMPL_GNUSTEP 1240#ifdef NS_IMPL_GNUSTEP
1241 [self insertItemWithItemIdentifier: identifier atIndex: idx]; 1241 [self insertItemWithItemIdentifier: identifier atIndex: idx];
1242#endif 1242#endif
1243 1243
1244 [item setTag: tag]; 1244 [item setTag: tag];
1245 [item setEnabled: enabled]; 1245 [item setEnabled: enabled];
1246 1246
diff --git a/src/nsterm.h b/src/nsterm.h
index fd8c9baa3e4..745b8a4145b 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -286,8 +286,7 @@ typedef float EmacsCGFloat;
286/* ========================================================================== 286/* ==========================================================================
287 287
288 File open/save panels 288 File open/save panels
289 This and next override methods to work around OS X behavior of 289 This and next override methods to handle keyboard input in panels.
290 restarting application loop when user dismisses panel.
291 290
292 ========================================================================== */ 291 ========================================================================== */
293 292
@@ -838,6 +837,9 @@ extern Lisp_Object ns_popup_dialog (Lisp_Object position, Lisp_Object contents,
838#define NSAPP_DATA2_RUNASSCRIPT 10 837#define NSAPP_DATA2_RUNASSCRIPT 10
839extern void ns_run_ascript (void); 838extern void ns_run_ascript (void);
840 839
840#define NSAPP_DATA2_RUNFILEDIALOG 11
841extern void ns_run_file_dialog (void);
842
841extern const char *ns_etc_directory (void); 843extern const char *ns_etc_directory (void);
842extern const char *ns_exec_path (void); 844extern const char *ns_exec_path (void);
843extern const char *ns_load_path (void); 845extern const char *ns_load_path (void);
diff --git a/src/nsterm.m b/src/nsterm.m
index 93f693fe55e..d7cea5c189a 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3603,7 +3603,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3603 3603
3604 /* Inform fd_handler that select should be called */ 3604 /* Inform fd_handler that select should be called */
3605 c = 'g'; 3605 c = 'g';
3606 emacs_write (selfds[1], &c, 1); 3606 emacs_write_sig (selfds[1], &c, 1);
3607 } 3607 }
3608 else if (nr == 0 && timeout) 3608 else if (nr == 0 && timeout)
3609 { 3609 {
@@ -3636,7 +3636,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3636 if (nr > 0 && readfds) 3636 if (nr > 0 && readfds)
3637 { 3637 {
3638 c = 's'; 3638 c = 's';
3639 emacs_write (selfds[1], &c, 1); 3639 emacs_write_sig (selfds[1], &c, 1);
3640 } 3640 }
3641 unblock_input (); 3641 unblock_input ();
3642 3642
@@ -4142,7 +4142,7 @@ ns_term_init (Lisp_Object display_name)
4142 4142
4143 if (selfds[0] == -1) 4143 if (selfds[0] == -1)
4144 { 4144 {
4145 if (pipe (selfds) == -1) 4145 if (pipe2 (selfds, O_CLOEXEC) != 0)
4146 { 4146 {
4147 fprintf (stderr, "Failed to create pipe: %s\n", 4147 fprintf (stderr, "Failed to create pipe: %s\n",
4148 emacs_strerror (errno)); 4148 emacs_strerror (errno));
@@ -4419,16 +4419,33 @@ ns_term_shutdown (int sig)
4419/* NSTRACE (sendEvent); */ 4419/* NSTRACE (sendEvent); */
4420/*fprintf (stderr, "received event of type %d\t%d\n", type);*/ 4420/*fprintf (stderr, "received event of type %d\t%d\n", type);*/
4421 4421
4422#ifdef NS_IMPL_COCOA 4422#ifdef NS_IMPL_GNUSTEP
4423 if (type == NSApplicationDefined 4423 // Keyboard events aren't propagated to file dialogs for some reason.
4424 && [theEvent data2] == NSAPP_DATA2_RUNASSCRIPT) 4424 if ([NSApp modalWindow] != nil &&
4425 (type == NSKeyDown || type == NSKeyUp || type == NSFlagsChanged))
4425 { 4426 {
4426 ns_run_ascript (); 4427 [[NSApp modalWindow] sendEvent: theEvent];
4427 [self stop: self];
4428 return; 4428 return;
4429 } 4429 }
4430#endif 4430#endif
4431 4431
4432 if (type == NSApplicationDefined)
4433 {
4434 switch ([theEvent data2])
4435 {
4436#ifdef NS_IMPL_COCOA
4437 case NSAPP_DATA2_RUNASSCRIPT:
4438 ns_run_ascript ();
4439 [self stop: self];
4440 return;
4441#endif
4442 case NSAPP_DATA2_RUNFILEDIALOG:
4443 ns_run_file_dialog ();
4444 [self stop: self];
4445 return;
4446 }
4447 }
4448
4432 if (type == NSCursorUpdate && window == nil) 4449 if (type == NSCursorUpdate && window == nil)
4433 { 4450 {
4434 fprintf (stderr, "Dropping external cursor update event.\n"); 4451 fprintf (stderr, "Dropping external cursor update event.\n");
diff --git a/src/print.c b/src/print.c
index f5ee47dc114..1257b46dda4 100644
--- a/src/print.c
+++ b/src/print.c
@@ -20,7 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 20
21 21
22#include <config.h> 22#include <config.h>
23#include <stdio.h> 23#include "sysstdio.h"
24 24
25#include "lisp.h" 25#include "lisp.h"
26#include "character.h" 26#include "character.h"
@@ -767,7 +767,7 @@ append to existing target file. */)
767 { 767 {
768 file = Fexpand_file_name (file, Qnil); 768 file = Fexpand_file_name (file, Qnil);
769 initial_stderr_stream = stderr; 769 initial_stderr_stream = stderr;
770 stderr = fopen (SSDATA (file), NILP (append) ? "w" : "a"); 770 stderr = emacs_fopen (SSDATA (file), NILP (append) ? "w" : "a");
771 if (stderr == NULL) 771 if (stderr == NULL)
772 { 772 {
773 stderr = initial_stderr_stream; 773 stderr = initial_stderr_stream;
@@ -1774,9 +1774,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1774#endif 1774#endif
1775 else if (WINDOWP (obj)) 1775 else if (WINDOWP (obj))
1776 { 1776 {
1777 int len; 1777 void *ptr = XWINDOW (obj);
1778 strout ("#<window ", -1, -1, printcharfun); 1778 int len = sprintf (buf, "#<window %p", ptr);
1779 len = sprintf (buf, "%p", XWINDOW (obj));
1780 strout (buf, len, len, printcharfun); 1779 strout (buf, len, len, printcharfun);
1781 if (BUFFERP (XWINDOW (obj)->contents)) 1780 if (BUFFERP (XWINDOW (obj)->contents))
1782 { 1781 {
@@ -1807,6 +1806,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1807 ptrdiff_t real_size, size; 1806 ptrdiff_t real_size, size;
1808 int len; 1807 int len;
1809#if 0 1808#if 0
1809 void *ptr = h;
1810 strout ("#<hash-table", -1, -1, printcharfun); 1810 strout ("#<hash-table", -1, -1, printcharfun);
1811 if (SYMBOLP (h->test)) 1811 if (SYMBOLP (h->test))
1812 { 1812 {
@@ -1819,9 +1819,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1819 len = sprintf (buf, "%"pD"d/%"pD"d", h->count, ASIZE (h->next)); 1819 len = sprintf (buf, "%"pD"d/%"pD"d", h->count, ASIZE (h->next));
1820 strout (buf, len, len, printcharfun); 1820 strout (buf, len, len, printcharfun);
1821 } 1821 }
1822 len = sprintf (buf, " %p", h); 1822 len = sprintf (buf, " %p>", ptr);
1823 strout (buf, len, len, printcharfun); 1823 strout (buf, len, len, printcharfun);
1824 PRINTCHAR ('>');
1825#endif 1824#endif
1826 /* Implement a readable output, e.g.: 1825 /* Implement a readable output, e.g.:
1827 #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */ 1826 #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
@@ -1901,6 +1900,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1901 else if (FRAMEP (obj)) 1900 else if (FRAMEP (obj))
1902 { 1901 {
1903 int len; 1902 int len;
1903 void *ptr = XFRAME (obj);
1904 Lisp_Object frame_name = XFRAME (obj)->name; 1904 Lisp_Object frame_name = XFRAME (obj)->name;
1905 1905
1906 strout ((FRAME_LIVE_P (XFRAME (obj)) 1906 strout ((FRAME_LIVE_P (XFRAME (obj))
@@ -1916,9 +1916,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1916 frame_name = build_string ("*INVALID*FRAME*NAME*"); 1916 frame_name = build_string ("*INVALID*FRAME*NAME*");
1917 } 1917 }
1918 print_string (frame_name, printcharfun); 1918 print_string (frame_name, printcharfun);
1919 len = sprintf (buf, " %p", XFRAME (obj)); 1919 len = sprintf (buf, " %p>", ptr);
1920 strout (buf, len, len, printcharfun); 1920 strout (buf, len, len, printcharfun);
1921 PRINTCHAR ('>');
1922 } 1921 }
1923 else if (FONTP (obj)) 1922 else if (FONTP (obj))
1924 { 1923 {
diff --git a/src/process.c b/src/process.c
index 9961697e671..8589acaa8b5 100644
--- a/src/process.c
+++ b/src/process.c
@@ -78,7 +78,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
78#endif 78#endif
79 79
80#ifdef HAVE_RES_INIT 80#ifdef HAVE_RES_INIT
81#include <netinet/in.h>
82#include <arpa/nameser.h> 81#include <arpa/nameser.h>
83#include <resolv.h> 82#include <resolv.h>
84#endif 83#endif
@@ -136,6 +135,37 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
136 EMACS_TIME *, void *); 135 EMACS_TIME *, void *);
137#endif 136#endif
138 137
138#ifndef SOCK_CLOEXEC
139# define SOCK_CLOEXEC 0
140#endif
141
142#ifndef HAVE_ACCEPT4
143
144/* Emulate GNU/Linux accept4 and socket well enough for this module. */
145
146static int
147close_on_exec (int fd)
148{
149 if (0 <= fd)
150 fcntl (fd, F_SETFD, FD_CLOEXEC);
151 return fd;
152}
153
154static int
155accept4 (int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
156{
157 return close_on_exec (accept (sockfd, addr, addrlen));
158}
159
160static int
161process_socket (int domain, int type, int protocol)
162{
163 return close_on_exec (socket (domain, type, protocol));
164}
165# undef socket
166# define socket(domain, type, protocol) process_socket (domain, type, protocol)
167#endif
168
139/* Work around GCC 4.7.0 bug with strict overflow checking; see 169/* Work around GCC 4.7.0 bug with strict overflow checking; see
140 <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>. 170 <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>.
141 These lines can be removed once the GCC bug is fixed. */ 171 These lines can be removed once the GCC bug is fixed. */
@@ -1586,6 +1616,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1586{ 1616{
1587 int inchannel, outchannel; 1617 int inchannel, outchannel;
1588 pid_t pid; 1618 pid_t pid;
1619 int vfork_errno;
1589 int sv[2]; 1620 int sv[2];
1590#ifndef WINDOWSNT 1621#ifndef WINDOWSNT
1591 int wait_child_setup[2]; 1622 int wait_child_setup[2];
@@ -1620,47 +1651,30 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1620 else 1651 else
1621#endif /* HAVE_PTYS */ 1652#endif /* HAVE_PTYS */
1622 { 1653 {
1623 int tem; 1654 if (pipe2 (sv, O_CLOEXEC) != 0)
1624 tem = pipe (sv);
1625 if (tem < 0)
1626 report_file_error ("Creating pipe", Qnil); 1655 report_file_error ("Creating pipe", Qnil);
1627 inchannel = sv[0]; 1656 inchannel = sv[0];
1628 forkout = sv[1]; 1657 forkout = sv[1];
1629 tem = pipe (sv); 1658 if (pipe2 (sv, O_CLOEXEC) != 0)
1630 if (tem < 0)
1631 { 1659 {
1660 int pipe_errno = errno;
1632 emacs_close (inchannel); 1661 emacs_close (inchannel);
1633 emacs_close (forkout); 1662 emacs_close (forkout);
1634 report_file_error ("Creating pipe", Qnil); 1663 report_file_errno ("Creating pipe", Qnil, pipe_errno);
1635 } 1664 }
1636 outchannel = sv[1]; 1665 outchannel = sv[1];
1637 forkin = sv[0]; 1666 forkin = sv[0];
1638 } 1667 }
1639 1668
1640#ifndef WINDOWSNT 1669#ifndef WINDOWSNT
1641 { 1670 if (pipe2 (wait_child_setup, O_CLOEXEC) != 0)
1642 int tem; 1671 report_file_error ("Creating pipe", Qnil);
1643
1644 tem = pipe (wait_child_setup);
1645 if (tem < 0)
1646 report_file_error ("Creating pipe", Qnil);
1647 tem = fcntl (wait_child_setup[1], F_GETFD, 0);
1648 if (tem >= 0)
1649 tem = fcntl (wait_child_setup[1], F_SETFD, tem | FD_CLOEXEC);
1650 if (tem < 0)
1651 {
1652 emacs_close (wait_child_setup[0]);
1653 emacs_close (wait_child_setup[1]);
1654 report_file_error ("Setting file descriptor flags", Qnil);
1655 }
1656 }
1657#endif 1672#endif
1658 1673
1659 fcntl (inchannel, F_SETFL, O_NONBLOCK); 1674 fcntl (inchannel, F_SETFL, O_NONBLOCK);
1660 fcntl (outchannel, F_SETFL, O_NONBLOCK); 1675 fcntl (outchannel, F_SETFL, O_NONBLOCK);
1661 1676
1662 /* Record this as an active process, with its channels. 1677 /* Record this as an active process, with its channels. */
1663 As a result, child_setup will close Emacs's side of the pipes. */
1664 chan_process[inchannel] = process; 1678 chan_process[inchannel] = process;
1665 XPROCESS (process)->infd = inchannel; 1679 XPROCESS (process)->infd = inchannel;
1666 XPROCESS (process)->outfd = outchannel; 1680 XPROCESS (process)->outfd = outchannel;
@@ -1740,7 +1754,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1740 tcgetattr (xforkin, &t); 1754 tcgetattr (xforkin, &t);
1741 t.c_lflag = LDISC1; 1755 t.c_lflag = LDISC1;
1742 if (tcsetattr (xforkin, TCSANOW, &t) < 0) 1756 if (tcsetattr (xforkin, TCSANOW, &t) < 0)
1743 emacs_write (1, "create_process/tcsetattr LDISC1 failed\n", 39); 1757 emacs_perror ("create_process/tcsetattr LDISC1");
1744 } 1758 }
1745#else 1759#else
1746#if defined (NTTYDISC) && defined (TIOCSETD) 1760#if defined (NTTYDISC) && defined (TIOCSETD)
@@ -1787,10 +1801,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1787 1801
1788 if (xforkin < 0) 1802 if (xforkin < 0)
1789 { 1803 {
1790 emacs_write (1, "Couldn't open the pty terminal ", 31); 1804 emacs_perror (pty_name);
1791 emacs_write (1, pty_name, strlen (pty_name)); 1805 _exit (EXIT_CANCELED);
1792 emacs_write (1, "\n", 1);
1793 _exit (1);
1794 } 1806 }
1795 1807
1796 } 1808 }
@@ -1802,12 +1814,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1802 SETUP_SLAVE_PTY; 1814 SETUP_SLAVE_PTY;
1803 } 1815 }
1804#endif /* SETUP_SLAVE_PTY */ 1816#endif /* SETUP_SLAVE_PTY */
1805#ifdef AIX
1806 /* On AIX, we've disabled SIGHUP above once we start a child on a pty.
1807 Now reenable it in the child, so it will die when we want it to. */
1808 if (pty_flag)
1809 signal (SIGHUP, SIG_DFL);
1810#endif
1811#endif /* HAVE_PTYS */ 1817#endif /* HAVE_PTYS */
1812 1818
1813 signal (SIGINT, SIG_DFL); 1819 signal (SIGINT, SIG_DFL);
@@ -1825,7 +1831,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1825 pid = child_setup (xforkin, xforkout, xforkout, 1831 pid = child_setup (xforkin, xforkout, xforkout,
1826 new_argv, 1, encoded_current_dir); 1832 new_argv, 1, encoded_current_dir);
1827#else /* not WINDOWSNT */ 1833#else /* not WINDOWSNT */
1828 emacs_close (wait_child_setup[0]);
1829 child_setup (xforkin, xforkout, xforkout, 1834 child_setup (xforkin, xforkout, xforkout,
1830 new_argv, 1, encoded_current_dir); 1835 new_argv, 1, encoded_current_dir);
1831#endif /* not WINDOWSNT */ 1836#endif /* not WINDOWSNT */
@@ -1833,6 +1838,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1833 1838
1834 /* Back in the parent process. */ 1839 /* Back in the parent process. */
1835 1840
1841 vfork_errno = errno;
1836 XPROCESS (process)->pid = pid; 1842 XPROCESS (process)->pid = pid;
1837 if (pid >= 0) 1843 if (pid >= 0)
1838 XPROCESS (process)->alive = 1; 1844 XPROCESS (process)->alive = 1;
@@ -1847,6 +1853,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1847 emacs_close (forkin); 1853 emacs_close (forkin);
1848 if (forkin != forkout && forkout >= 0) 1854 if (forkin != forkout && forkout >= 0)
1849 emacs_close (forkout); 1855 emacs_close (forkout);
1856 report_file_errno ("Doing vfork", Qnil, vfork_errno);
1850 } 1857 }
1851 else 1858 else
1852 { 1859 {
@@ -1892,10 +1899,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1892 } 1899 }
1893#endif 1900#endif
1894 } 1901 }
1895
1896 /* Now generate the error if vfork failed. */
1897 if (pid < 0)
1898 report_file_error ("Doing vfork", Qnil);
1899} 1902}
1900 1903
1901void 1904void
@@ -3136,7 +3139,8 @@ usage: (make-network-process &rest ARGS) */)
3136 retry_connect: 3139 retry_connect:
3137#endif 3140#endif
3138 3141
3139 s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol); 3142 s = socket (lres->ai_family, lres->ai_socktype | SOCK_CLOEXEC,
3143 lres->ai_protocol);
3140 if (s < 0) 3144 if (s < 0)
3141 { 3145 {
3142 xerrno = errno; 3146 xerrno = errno;
@@ -3260,12 +3264,11 @@ usage: (make-network-process &rest ARGS) */)
3260 3264
3261 len = sizeof xerrno; 3265 len = sizeof xerrno;
3262 eassert (FD_ISSET (s, &fdset)); 3266 eassert (FD_ISSET (s, &fdset));
3263 if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) == -1) 3267 if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) < 0)
3264 report_file_error ("getsockopt failed", Qnil); 3268 report_file_error ("getsockopt failed", Qnil);
3265 if (xerrno) 3269 if (xerrno)
3266 errno = xerrno, report_file_error ("error during connect", Qnil); 3270 report_file_errno ("error during connect", Qnil, xerrno);
3267 else 3271 break;
3268 break;
3269 } 3272 }
3270#endif /* !WINDOWSNT */ 3273#endif /* !WINDOWSNT */
3271 3274
@@ -3349,11 +3352,10 @@ usage: (make-network-process &rest ARGS) */)
3349 if (is_non_blocking_client) 3352 if (is_non_blocking_client)
3350 return Qnil; 3353 return Qnil;
3351 3354
3352 errno = xerrno; 3355 report_file_errno ((is_server
3353 if (is_server) 3356 ? "make server process failed"
3354 report_file_error ("make server process failed", contact); 3357 : "make client process failed"),
3355 else 3358 contact, xerrno);
3356 report_file_error ("make client process failed", contact);
3357 } 3359 }
3358 3360
3359 inch = s; 3361 inch = s;
@@ -3533,7 +3535,7 @@ format; see the description of ADDRESS in `make-network-process'. */)
3533 int s; 3535 int s;
3534 Lisp_Object res; 3536 Lisp_Object res;
3535 3537
3536 s = socket (AF_INET, SOCK_STREAM, 0); 3538 s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
3537 if (s < 0) 3539 if (s < 0)
3538 return Qnil; 3540 return Qnil;
3539 3541
@@ -3544,14 +3546,14 @@ format; see the description of ADDRESS in `make-network-process'. */)
3544 ifconf.ifc_len = buf_size; 3546 ifconf.ifc_len = buf_size;
3545 if (ioctl (s, SIOCGIFCONF, &ifconf)) 3547 if (ioctl (s, SIOCGIFCONF, &ifconf))
3546 { 3548 {
3547 close (s); 3549 emacs_close (s);
3548 xfree (buf); 3550 xfree (buf);
3549 return Qnil; 3551 return Qnil;
3550 } 3552 }
3551 } 3553 }
3552 while (ifconf.ifc_len == buf_size); 3554 while (ifconf.ifc_len == buf_size);
3553 3555
3554 close (s); 3556 emacs_close (s);
3555 3557
3556 res = Qnil; 3558 res = Qnil;
3557 ifreq = ifconf.ifc_req; 3559 ifreq = ifconf.ifc_req;
@@ -3689,7 +3691,7 @@ FLAGS is the current flags of the interface. */)
3689 error ("interface name too long"); 3691 error ("interface name too long");
3690 strcpy (rq.ifr_name, SSDATA (ifname)); 3692 strcpy (rq.ifr_name, SSDATA (ifname));
3691 3693
3692 s = socket (AF_INET, SOCK_STREAM, 0); 3694 s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
3693 if (s < 0) 3695 if (s < 0)
3694 return Qnil; 3696 return Qnil;
3695 3697
@@ -3808,7 +3810,7 @@ FLAGS is the current flags of the interface. */)
3808#endif 3810#endif
3809 res = Fcons (elt, res); 3811 res = Fcons (elt, res);
3810 3812
3811 close (s); 3813 emacs_close (s);
3812 3814
3813 return any ? res : Qnil; 3815 return any ? res : Qnil;
3814} 3816}
@@ -3985,7 +3987,7 @@ server_accept_connection (Lisp_Object server, int channel)
3985 } saddr; 3987 } saddr;
3986 socklen_t len = sizeof saddr; 3988 socklen_t len = sizeof saddr;
3987 3989
3988 s = accept (channel, &saddr.sa, &len); 3990 s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC);
3989 3991
3990 if (s < 0) 3992 if (s < 0)
3991 { 3993 {
@@ -4621,20 +4623,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
4621 if (xerrno == EINTR) 4623 if (xerrno == EINTR)
4622 no_avail = 1; 4624 no_avail = 1;
4623 else if (xerrno == EBADF) 4625 else if (xerrno == EBADF)
4624 { 4626 emacs_abort ();
4625#ifdef AIX
4626 /* AIX doesn't handle PTY closure the same way BSD does. On AIX,
4627 the child's closure of the pts gives the parent a SIGHUP, and
4628 the ptc file descriptor is automatically closed,
4629 yielding EBADF here or at select() call above.
4630 So, SIGHUP is ignored (see def of PTY_TTY_NAME_SPRINTF
4631 in m/ibmrt-aix.h), and here we just ignore the select error.
4632 Cleanup occurs c/o status_notify after SIGCHLD. */
4633 no_avail = 1; /* Cannot depend on values returned */
4634#else
4635 emacs_abort ();
4636#endif
4637 }
4638 else 4627 else
4639 error ("select error: %s", emacs_strerror (xerrno)); 4628 error ("select error: %s", emacs_strerror (xerrno));
4640 } 4629 }
@@ -5490,7 +5479,7 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
5490 written = emacs_gnutls_write (p, cur_buf, cur_len); 5479 written = emacs_gnutls_write (p, cur_buf, cur_len);
5491 else 5480 else
5492#endif 5481#endif
5493 written = emacs_write (outfd, cur_buf, cur_len); 5482 written = emacs_write_sig (outfd, cur_buf, cur_len);
5494 rv = (written ? 0 : -1); 5483 rv = (written ? 0 : -1);
5495#ifdef ADAPTIVE_READ_BUFFERING 5484#ifdef ADAPTIVE_READ_BUFFERING
5496 if (p->read_output_delay > 0 5485 if (p->read_output_delay > 0
@@ -6859,32 +6848,6 @@ setup_process_coding_systems (Lisp_Object process)
6859#endif 6848#endif
6860} 6849}
6861 6850
6862/* Close all descriptors currently in use for communication
6863 with subprocess. This is used in a newly-forked subprocess
6864 to get rid of irrelevant descriptors. */
6865
6866void
6867close_process_descs (void)
6868{
6869#ifndef DOS_NT
6870 int i;
6871 for (i = 0; i < MAXDESC; i++)
6872 {
6873 Lisp_Object process;
6874 process = chan_process[i];
6875 if (!NILP (process))
6876 {
6877 int in = XPROCESS (process)->infd;
6878 int out = XPROCESS (process)->outfd;
6879 if (in >= 0)
6880 emacs_close (in);
6881 if (out >= 0 && in != out)
6882 emacs_close (out);
6883 }
6884 }
6885#endif
6886}
6887
6888DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0, 6851DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
6889 doc: /* Return the (or a) process associated with BUFFER. 6852 doc: /* Return the (or a) process associated with BUFFER.
6890BUFFER may be a buffer or the name of one. */) 6853BUFFER may be a buffer or the name of one. */)
diff --git a/src/process.h b/src/process.h
index e7ee5f9adde..8ae33aebf39 100644
--- a/src/process.h
+++ b/src/process.h
@@ -198,6 +198,14 @@ extern Lisp_Object QCspeed;
198extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven; 198extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
199extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary; 199extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
200 200
201/* Exit statuses for GNU programs that exec other programs. */
202enum
203{
204 EXIT_CANCELED = 125, /* Internal error prior to exec attempt. */
205 EXIT_CANNOT_INVOKE = 126, /* Program located, but not usable. */
206 EXIT_ENOENT = 127 /* Could not find program to exec. */
207};
208
201/* Defined in callproc.c. */ 209/* Defined in callproc.c. */
202 210
203extern void block_child_signal (void); 211extern void block_child_signal (void);
diff --git a/src/profiler.c b/src/profiler.c
index aba81344c68..c86fb47d21d 100644
--- a/src/profiler.c
+++ b/src/profiler.c
@@ -568,12 +568,12 @@ to make room for new entries. */);
568 profiler_log_size = 10000; 568 profiler_log_size = 10000;
569 569
570 DEFSYM (Qprofiler_backtrace_equal, "profiler-backtrace-equal"); 570 DEFSYM (Qprofiler_backtrace_equal, "profiler-backtrace-equal");
571 { 571
572 struct hash_table_test test 572 hashtest_profiler.name = Qprofiler_backtrace_equal;
573 = { Qprofiler_backtrace_equal, Qnil, Qnil, 573 hashtest_profiler.user_hash_function = Qnil;
574 cmpfn_profiler, hashfn_profiler }; 574 hashtest_profiler.user_cmp_function = Qnil;
575 hashtest_profiler = test; 575 hashtest_profiler.cmpfn = cmpfn_profiler;
576 } 576 hashtest_profiler.hashfn = hashfn_profiler;
577 577
578 defsubr (&Sfunction_equal); 578 defsubr (&Sfunction_equal);
579 579
diff --git a/src/ralloc.c b/src/ralloc.c
index 13fd65cbb0c..5f25ef2c320 100644
--- a/src/ralloc.c
+++ b/src/ralloc.c
@@ -43,8 +43,6 @@ extern size_t __malloc_extra_blocks;
43#else /* not emacs */ 43#else /* not emacs */
44 44
45#include <stddef.h> 45#include <stddef.h>
46
47#include <unistd.h>
48#include <malloc.h> 46#include <malloc.h>
49 47
50#endif /* not emacs */ 48#endif /* not emacs */
diff --git a/src/regex.c b/src/regex.c
index 79fb28ba12a..39adb080efd 100644
--- a/src/regex.c
+++ b/src/regex.c
@@ -531,8 +531,10 @@ init_syntax_once (void)
531/* Type of source-pattern and string chars. */ 531/* Type of source-pattern and string chars. */
532#ifdef _MSC_VER 532#ifdef _MSC_VER
533typedef unsigned char re_char; 533typedef unsigned char re_char;
534typedef const re_char const_re_char;
534#else 535#else
535typedef const unsigned char re_char; 536typedef const unsigned char re_char;
537typedef re_char const_re_char;
536#endif 538#endif
537 539
538typedef char boolean; 540typedef char boolean;
@@ -2015,7 +2017,7 @@ struct range_table_work_area
2015 2017
2016/* Map a string to the char class it names (if any). */ 2018/* Map a string to the char class it names (if any). */
2017re_wctype_t 2019re_wctype_t
2018re_wctype (const re_char *str) 2020re_wctype (const_re_char *str)
2019{ 2021{
2020 const char *string = (const char *) str; 2022 const char *string = (const char *) str;
2021 if (STREQ (string, "alnum")) return RECC_ALNUM; 2023 if (STREQ (string, "alnum")) return RECC_ALNUM;
@@ -2409,7 +2411,8 @@ do { \
2409 } while (0) 2411 } while (0)
2410 2412
2411static reg_errcode_t 2413static reg_errcode_t
2412regex_compile (const re_char *pattern, size_t size, reg_syntax_t syntax, struct re_pattern_buffer *bufp) 2414regex_compile (const_re_char *pattern, size_t size, reg_syntax_t syntax,
2415 struct re_pattern_buffer *bufp)
2413{ 2416{
2414 /* We fetch characters from PATTERN here. */ 2417 /* We fetch characters from PATTERN here. */
2415 register re_wchar_t c, c1; 2418 register re_wchar_t c, c1;
@@ -3765,7 +3768,7 @@ insert_op2 (re_opcode_t op, unsigned char *loc, int arg1, int arg2, unsigned cha
3765 least one character before the ^. */ 3768 least one character before the ^. */
3766 3769
3767static boolean 3770static boolean
3768at_begline_loc_p (const re_char *pattern, const re_char *p, reg_syntax_t syntax) 3771at_begline_loc_p (const_re_char *pattern, const_re_char *p, reg_syntax_t syntax)
3769{ 3772{
3770 re_char *prev = p - 2; 3773 re_char *prev = p - 2;
3771 boolean odd_backslashes; 3774 boolean odd_backslashes;
@@ -3806,7 +3809,7 @@ at_begline_loc_p (const re_char *pattern, const re_char *p, reg_syntax_t syntax)
3806 at least one character after the $, i.e., `P < PEND'. */ 3809 at least one character after the $, i.e., `P < PEND'. */
3807 3810
3808static boolean 3811static boolean
3809at_endline_loc_p (const re_char *p, const re_char *pend, reg_syntax_t syntax) 3812at_endline_loc_p (const_re_char *p, const_re_char *pend, reg_syntax_t syntax)
3810{ 3813{
3811 re_char *next = p; 3814 re_char *next = p;
3812 boolean next_backslash = *next == '\\'; 3815 boolean next_backslash = *next == '\\';
@@ -3850,7 +3853,8 @@ group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum)
3850 Return -1 if fastmap was not updated accurately. */ 3853 Return -1 if fastmap was not updated accurately. */
3851 3854
3852static int 3855static int
3853analyse_first (const re_char *p, const re_char *pend, char *fastmap, const int multibyte) 3856analyse_first (const_re_char *p, const_re_char *pend, char *fastmap,
3857 const int multibyte)
3854{ 3858{
3855 int j, k; 3859 int j, k;
3856 boolean not; 3860 boolean not;
@@ -4594,7 +4598,7 @@ static int bcmp_translate (re_char *s1, re_char *s2,
4594/* If the operation is a match against one or more chars, 4598/* If the operation is a match against one or more chars,
4595 return a pointer to the next operation, else return NULL. */ 4599 return a pointer to the next operation, else return NULL. */
4596static re_char * 4600static re_char *
4597skip_one_char (const re_char *p) 4601skip_one_char (const_re_char *p)
4598{ 4602{
4599 switch (*p++) 4603 switch (*p++)
4600 { 4604 {
@@ -4636,7 +4640,7 @@ skip_one_char (const re_char *p)
4636 4640
4637/* Jump over non-matching operations. */ 4641/* Jump over non-matching operations. */
4638static re_char * 4642static re_char *
4639skip_noops (const re_char *p, const re_char *pend) 4643skip_noops (const_re_char *p, const_re_char *pend)
4640{ 4644{
4641 int mcnt; 4645 int mcnt;
4642 while (p < pend) 4646 while (p < pend)
@@ -4663,7 +4667,8 @@ skip_noops (const re_char *p, const re_char *pend)
4663 4667
4664/* Non-zero if "p1 matches something" implies "p2 fails". */ 4668/* Non-zero if "p1 matches something" implies "p2 fails". */
4665static int 4669static int
4666mutually_exclusive_p (struct re_pattern_buffer *bufp, const re_char *p1, const re_char *p2) 4670mutually_exclusive_p (struct re_pattern_buffer *bufp, const_re_char *p1,
4671 const_re_char *p2)
4667{ 4672{
4668 re_opcode_t op2; 4673 re_opcode_t op2;
4669 const boolean multibyte = RE_MULTIBYTE_P (bufp); 4674 const boolean multibyte = RE_MULTIBYTE_P (bufp);
@@ -4922,8 +4927,8 @@ WEAK_ALIAS (__re_match_2, re_match_2)
4922/* This is a separate function so that we can force an alloca cleanup 4927/* This is a separate function so that we can force an alloca cleanup
4923 afterwards. */ 4928 afterwards. */
4924static regoff_t 4929static regoff_t
4925re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1, 4930re_match_2_internal (struct re_pattern_buffer *bufp, const_re_char *string1,
4926 size_t size1, const re_char *string2, size_t size2, 4931 size_t size1, const_re_char *string2, size_t size2,
4927 ssize_t pos, struct re_registers *regs, ssize_t stop) 4932 ssize_t pos, struct re_registers *regs, ssize_t stop)
4928{ 4933{
4929 /* General temporaries. */ 4934 /* General temporaries. */
@@ -6265,7 +6270,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
6265 bytes; nonzero otherwise. */ 6270 bytes; nonzero otherwise. */
6266 6271
6267static int 6272static int
6268bcmp_translate (const re_char *s1, const re_char *s2, register ssize_t len, 6273bcmp_translate (const_re_char *s1, const_re_char *s2, register ssize_t len,
6269 RE_TRANSLATE_TYPE translate, const int target_multibyte) 6274 RE_TRANSLATE_TYPE translate, const int target_multibyte)
6270{ 6275{
6271 register re_char *p1 = s1, *p2 = s2; 6276 register re_char *p1 = s1, *p2 = s2;
@@ -6434,7 +6439,7 @@ re_exec (const char *s)
6434 the return codes and their meanings.) */ 6439 the return codes and their meanings.) */
6435 6440
6436reg_errcode_t 6441reg_errcode_t
6437regcomp (regex_t *__restrict preg, const char *__restrict pattern, 6442regcomp (regex_t *_Restrict_ preg, const char *_Restrict_ pattern,
6438 int cflags) 6443 int cflags)
6439{ 6444{
6440 reg_errcode_t ret; 6445 reg_errcode_t ret;
@@ -6515,8 +6520,8 @@ WEAK_ALIAS (__regcomp, regcomp)
6515 We return 0 if we find a match and REG_NOMATCH if not. */ 6520 We return 0 if we find a match and REG_NOMATCH if not. */
6516 6521
6517reg_errcode_t 6522reg_errcode_t
6518regexec (const regex_t *__restrict preg, const char *__restrict string, 6523regexec (const regex_t *_Restrict_ preg, const char *_Restrict_ string,
6519 size_t nmatch, regmatch_t pmatch[__restrict_arr], int eflags) 6524 size_t nmatch, regmatch_t pmatch[_Restrict_arr_], int eflags)
6520{ 6525{
6521 regoff_t ret; 6526 regoff_t ret;
6522 struct re_registers regs; 6527 struct re_registers regs;
diff --git a/src/regex.h b/src/regex.h
index 8fe7ba16adc..bb737df5239 100644
--- a/src/regex.h
+++ b/src/regex.h
@@ -528,31 +528,41 @@ extern int re_exec (const char *);
528#endif 528#endif
529 529
530/* GCC 2.95 and later have "__restrict"; C99 compilers have 530/* GCC 2.95 and later have "__restrict"; C99 compilers have
531 "restrict", and "configure" may have defined "restrict". */ 531 "restrict", and "configure" may have defined "restrict".
532#ifndef __restrict 532 Other compilers use __restrict, __restrict__, and _Restrict, and
533# if ! (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)) 533 'configure' might #define 'restrict' to those words, so pick a
534# if defined restrict || 199901L <= __STDC_VERSION__ 534 different name. */
535# define __restrict restrict 535#ifndef _Restrict_
536# else 536# if 199901L <= __STDC_VERSION__
537# define __restrict 537# define _Restrict_ restrict
538# endif 538# elif 2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)
539# define _Restrict_ __restrict
540# else
541# define _Restrict_
539# endif 542# endif
540#endif 543#endif
541/* For now conditionally define __restrict_arr to expand to nothing. 544/* gcc 3.1 and up support the [restrict] syntax. Don't trust
542 Ideally we would have a test for the compiler which allows defining 545 sys/cdefs.h's definition of __restrict_arr, though, as it
543 it to restrict. */ 546 mishandles gcc -ansi -pedantic. */
544#ifndef __restrict_arr 547#ifndef _Restrict_arr_
545# define __restrict_arr 548# if ((199901L <= __STDC_VERSION__ \
549 || ((3 < __GNUC__ || (3 == __GNUC__ && 1 <= __GNUC_MINOR__)) \
550 && !defined __STRICT_ANSI__)) \
551 && !defined __GNUG__)
552# define _Restrict_arr_ _Restrict_
553# else
554# define _Restrict_arr_
555# endif
546#endif 556#endif
547 557
548/* POSIX compatibility. */ 558/* POSIX compatibility. */
549extern reg_errcode_t regcomp (regex_t *__restrict __preg, 559extern reg_errcode_t regcomp (regex_t *_Restrict_ __preg,
550 const char *__restrict __pattern, 560 const char *_Restrict_ __pattern,
551 int __cflags); 561 int __cflags);
552 562
553extern reg_errcode_t regexec (const regex_t *__restrict __preg, 563extern reg_errcode_t regexec (const regex_t *_Restrict_ __preg,
554 const char *__restrict __string, size_t __nmatch, 564 const char *_Restrict_ __string, size_t __nmatch,
555 regmatch_t __pmatch[__restrict_arr], 565 regmatch_t __pmatch[_Restrict_arr_],
556 int __eflags); 566 int __eflags);
557 567
558extern size_t regerror (int __errcode, const regex_t * __preg, 568extern size_t regerror (int __errcode, const regex_t * __preg,
diff --git a/src/search.c b/src/search.c
index 8b4d39c7811..19cc08f84c4 100644
--- a/src/search.c
+++ b/src/search.c
@@ -22,10 +22,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22#include <config.h> 22#include <config.h>
23 23
24#include "lisp.h" 24#include "lisp.h"
25#include "syntax.h"
26#include "category.h" 25#include "category.h"
27#include "character.h" 26#include "character.h"
28#include "buffer.h" 27#include "buffer.h"
28#include "syntax.h"
29#include "charset.h" 29#include "charset.h"
30#include "region-cache.h" 30#include "region-cache.h"
31#include "commands.h" 31#include "commands.h"
diff --git a/src/sheap.c b/src/sheap.c
index f8eec753268..54eef60c27d 100644
--- a/src/sheap.c
+++ b/src/sheap.c
@@ -25,7 +25,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
25 25
26#include <unistd.h> 26#include <unistd.h>
27 27
28#ifdef __x86_64__
29#define STATIC_HEAP_SIZE (18 * 1024 * 1024)
30#else
28#define STATIC_HEAP_SIZE (13 * 1024 * 1024) 31#define STATIC_HEAP_SIZE (13 * 1024 * 1024)
32#endif
29 33
30int debug_sheap = 0; 34int debug_sheap = 0;
31 35
diff --git a/src/sound.c b/src/sound.c
index 7f0ede5b398..5ce185ea60e 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -879,7 +879,7 @@ vox_init (struct sound_device *sd)
879static void 879static void
880vox_write (struct sound_device *sd, const char *buffer, ptrdiff_t nbytes) 880vox_write (struct sound_device *sd, const char *buffer, ptrdiff_t nbytes)
881{ 881{
882 if (emacs_write (sd->fd, buffer, nbytes) != nbytes) 882 if (emacs_write_sig (sd->fd, buffer, nbytes) != nbytes)
883 sound_perror ("Error writing to sound device"); 883 sound_perror ("Error writing to sound device");
884} 884}
885 885
diff --git a/src/syntax.c b/src/syntax.c
index ea15cf68c43..6d52d115889 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -20,6 +20,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 20
21#include <config.h> 21#include <config.h>
22 22
23#define SYNTAX_INLINE EXTERN_INLINE
24
23#include <sys/types.h> 25#include <sys/types.h>
24 26
25#include "lisp.h" 27#include "lisp.h"
@@ -58,54 +60,86 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
58 For style c (like the nested flag), the flag can be placed on any of 60 For style c (like the nested flag), the flag can be placed on any of
59 the chars. */ 61 the chars. */
60 62
61/* These macros extract specific flags from an integer 63/* These functions extract specific flags from an integer
62 that holds the syntax code and the flags. */ 64 that holds the syntax code and the flags. */
63 65
64#define SYNTAX_FLAGS_COMSTART_FIRST(flags) (((flags) >> 16) & 1) 66static bool
65 67SYNTAX_FLAGS_COMSTART_FIRST (int flags)
66#define SYNTAX_FLAGS_COMSTART_SECOND(flags) (((flags) >> 17) & 1) 68{
67 69 return (flags >> 16) & 1;
68#define SYNTAX_FLAGS_COMEND_FIRST(flags) (((flags) >> 18) & 1) 70}
69 71static bool
70#define SYNTAX_FLAGS_COMEND_SECOND(flags) (((flags) >> 19) & 1) 72SYNTAX_FLAGS_COMSTART_SECOND (int flags)
71 73{
72#define SYNTAX_FLAGS_PREFIX(flags) (((flags) >> 20) & 1) 74 return (flags >> 17) & 1;
75}
76static bool
77SYNTAX_FLAGS_COMEND_FIRST (int flags)
78{
79 return (flags >> 18) & 1;
80}
81static bool
82SYNTAX_FLAGS_COMEND_SECOND (int flags)
83{
84 return (flags >> 19) & 1;
85}
86static bool
87SYNTAX_FLAGS_PREFIX (int flags)
88{
89 return (flags >> 20) & 1;
90}
91static bool
92SYNTAX_FLAGS_COMMENT_STYLEB (int flags)
93{
94 return (flags >> 21) & 1;
95}
96static bool
97SYNTAX_FLAGS_COMMENT_STYLEC (int flags)
98{
99 return (flags >> 23) & 1;
100}
101static int
102SYNTAX_FLAGS_COMMENT_STYLEC2 (int flags)
103{
104 return (flags >> 22) & 2; /* SYNTAX_FLAGS_COMMENT_STYLEC (flags) * 2 */
105}
106static bool
107SYNTAX_FLAGS_COMMENT_NESTED (int flags)
108{
109 return (flags >> 22) & 1;
110}
73 111
74#define SYNTAX_FLAGS_COMMENT_STYLEB(flags) (((flags) >> 21) & 1)
75#define SYNTAX_FLAGS_COMMENT_STYLEC(flags) (((flags) >> 23) & 1)
76#define SYNTAX_FLAGS_COMMENT_STYLEC2(flags) (((flags) >> 22) & 2) /* C * 2 */
77/* FLAGS should be the flags of the main char of the comment marker, e.g. 112/* FLAGS should be the flags of the main char of the comment marker, e.g.
78 the second for comstart and the first for comend. */ 113 the second for comstart and the first for comend. */
79#define SYNTAX_FLAGS_COMMENT_STYLE(flags, other_flags) \ 114static int
80 (SYNTAX_FLAGS_COMMENT_STYLEB (flags) \ 115SYNTAX_FLAGS_COMMENT_STYLE (int flags, int other_flags)
81 | SYNTAX_FLAGS_COMMENT_STYLEC2 (flags) \ 116{
82 | SYNTAX_FLAGS_COMMENT_STYLEC2 (other_flags)) 117 return (SYNTAX_FLAGS_COMMENT_STYLEB (flags)
83 118 | SYNTAX_FLAGS_COMMENT_STYLEC2 (flags)
84#define SYNTAX_FLAGS_COMMENT_NESTED(flags) (((flags) >> 22) & 1) 119 | SYNTAX_FLAGS_COMMENT_STYLEC2 (other_flags));
120}
85 121
86/* These macros extract a particular flag for a given character. */ 122/* Extract a particular flag for a given character. */
87 123
88#define SYNTAX_COMEND_FIRST(c) \ 124static bool
89 (SYNTAX_FLAGS_COMEND_FIRST (SYNTAX_WITH_FLAGS (c))) 125SYNTAX_COMEND_FIRST (int c)
90#define SYNTAX_PREFIX(c) (SYNTAX_FLAGS_PREFIX (SYNTAX_WITH_FLAGS (c))) 126{
127 return SYNTAX_FLAGS_COMEND_FIRST (SYNTAX_WITH_FLAGS (c));
128}
91 129
92/* We use these constants in place for comment-style and 130/* We use these constants in place for comment-style and
93 string-ender-char to distinguish comments/strings started by 131 string-ender-char to distinguish comments/strings started by
94 comment_fence and string_fence codes. */ 132 comment_fence and string_fence codes. */
95 133
96#define ST_COMMENT_STYLE (256 + 1) 134enum
97#define ST_STRING_STYLE (256 + 2) 135 {
136 ST_COMMENT_STYLE = 256 + 1,
137 ST_STRING_STYLE = 256 + 2
138 };
98 139
99static Lisp_Object Qsyntax_table_p; 140static Lisp_Object Qsyntax_table_p;
100static Lisp_Object Qsyntax_table, Qscan_error; 141static Lisp_Object Qsyntax_table, Qscan_error;
101 142
102#ifndef __GNUC__
103/* Used as a temporary in SYNTAX_ENTRY and other macros in syntax.h,
104 if not compiled with GCC. No need to mark it, since it is used
105 only very temporarily. */
106Lisp_Object syntax_temp;
107#endif
108
109/* This is the internal form of the parse state used in parse-partial-sexp. */ 143/* This is the internal form of the parse state used in parse-partial-sexp. */
110 144
111struct lisp_parse_state 145struct lisp_parse_state
@@ -162,14 +196,107 @@ bset_syntax_table (struct buffer *b, Lisp_Object val)
162bool 196bool
163syntax_prefix_flag_p (int c) 197syntax_prefix_flag_p (int c)
164{ 198{
165 return SYNTAX_PREFIX (c); 199 return SYNTAX_FLAGS_PREFIX (SYNTAX_WITH_FLAGS (c));
166} 200}
167 201
168struct gl_state_s gl_state; /* Global state of syntax parser. */ 202struct gl_state_s gl_state; /* Global state of syntax parser. */
169 203
170#define INTERVALS_AT_ONCE 10 /* 1 + max-number of intervals 204enum { INTERVALS_AT_ONCE = 10 }; /* 1 + max-number of intervals
171 to scan to property-change. */ 205 to scan to property-change. */
172 206
207/* Set the syntax entry VAL for char C in table TABLE. */
208
209static void
210SET_RAW_SYNTAX_ENTRY (Lisp_Object table, int c, Lisp_Object val)
211{
212 CHAR_TABLE_SET (table, c, val);
213}
214
215/* Set the syntax entry VAL for char-range RANGE in table TABLE.
216 RANGE is a cons (FROM . TO) specifying the range of characters. */
217
218static void
219SET_RAW_SYNTAX_ENTRY_RANGE (Lisp_Object table, Lisp_Object range,
220 Lisp_Object val)
221{
222 Fset_char_table_range (table, range, val);
223}
224
225/* Extract the information from the entry for character C
226 in the current syntax table. */
227
228static Lisp_Object
229SYNTAX_MATCH (int c)
230{
231 Lisp_Object ent = SYNTAX_ENTRY (c);
232 return CONSP (ent) ? XCDR (ent) : Qnil;
233}
234
235/* This should be called with FROM at the start of forward
236 search, or after the last position of the backward search. It
237 makes sure that the first char is picked up with correct table, so
238 one does not need to call UPDATE_SYNTAX_TABLE immediately after the
239 call.
240 Sign of COUNT gives the direction of the search.
241 */
242
243static void
244SETUP_SYNTAX_TABLE (ptrdiff_t from, ptrdiff_t count)
245{
246 SETUP_BUFFER_SYNTAX_TABLE ();
247 gl_state.b_property = BEGV;
248 gl_state.e_property = ZV + 1;
249 gl_state.object = Qnil;
250 gl_state.offset = 0;
251 if (parse_sexp_lookup_properties)
252 if (count > 0 || from > BEGV)
253 update_syntax_table (count > 0 ? from : from - 1, count, 1, Qnil);
254}
255
256/* Same as above, but in OBJECT. If OBJECT is nil, use current buffer.
257 If it is t (which is only used in fast_c_string_match_ignore_case),
258 ignore properties altogether.
259
260 This is meant for regex.c to use. For buffers, regex.c passes arguments
261 to the UPDATE_SYNTAX_TABLE functions which are relative to BEGV.
262 So if it is a buffer, we set the offset field to BEGV. */
263
264void
265SETUP_SYNTAX_TABLE_FOR_OBJECT (Lisp_Object object,
266 ptrdiff_t from, ptrdiff_t count)
267{
268 SETUP_BUFFER_SYNTAX_TABLE ();
269 gl_state.object = object;
270 if (BUFFERP (gl_state.object))
271 {
272 struct buffer *buf = XBUFFER (gl_state.object);
273 gl_state.b_property = 1;
274 gl_state.e_property = BUF_ZV (buf) - BUF_BEGV (buf) + 1;
275 gl_state.offset = BUF_BEGV (buf) - 1;
276 }
277 else if (NILP (gl_state.object))
278 {
279 gl_state.b_property = 1;
280 gl_state.e_property = ZV - BEGV + 1;
281 gl_state.offset = BEGV - 1;
282 }
283 else if (EQ (gl_state.object, Qt))
284 {
285 gl_state.b_property = 0;
286 gl_state.e_property = PTRDIFF_MAX;
287 gl_state.offset = 0;
288 }
289 else
290 {
291 gl_state.b_property = 0;
292 gl_state.e_property = 1 + SCHARS (gl_state.object);
293 gl_state.offset = 0;
294 }
295 if (parse_sexp_lookup_properties)
296 update_syntax_table (from + gl_state.offset - (count <= 0),
297 count, 1, gl_state.object);
298}
299
173/* Update gl_state to an appropriate interval which contains CHARPOS. The 300/* Update gl_state to an appropriate interval which contains CHARPOS. The
174 sign of COUNT give the relative position of CHARPOS wrt the previously 301 sign of COUNT give the relative position of CHARPOS wrt the previously
175 valid interval. If INIT, only [be]_property fields of gl_state are 302 valid interval. If INIT, only [be]_property fields of gl_state are
@@ -1751,7 +1878,7 @@ skip_chars (bool forwardp, Lisp_Object string, Lisp_Object lim,
1751 } 1878 }
1752 1879
1753 immediate_quit = 1; 1880 immediate_quit = 1;
1754 /* This code may look up syntax tables using macros that rely on the 1881 /* This code may look up syntax tables using functions that rely on the
1755 gl_state object. To make sure this object is not out of date, 1882 gl_state object. To make sure this object is not out of date,
1756 let's initialize it manually. 1883 let's initialize it manually.
1757 We ignore syntax-table text-properties for now, since that's 1884 We ignore syntax-table text-properties for now, since that's
@@ -2426,11 +2553,13 @@ between them, return t; otherwise return nil. */)
2426} 2553}
2427 2554
2428/* Return syntax code of character C if C is an ASCII character 2555/* Return syntax code of character C if C is an ASCII character
2429 or `multibyte_symbol_p' is zero. Otherwise, return Ssymbol. */ 2556 or if MULTIBYTE_SYMBOL_P is false. Otherwise, return Ssymbol. */
2430 2557
2431#define SYNTAX_WITH_MULTIBYTE_CHECK(c) \ 2558static enum syntaxcode
2432 ((ASCII_CHAR_P (c) || !multibyte_symbol_p) \ 2559syntax_multibyte (int c, bool multibyte_symbol_p)
2433 ? SYNTAX (c) : Ssymbol) 2560{
2561 return ASCII_CHAR_P (c) || !multibyte_symbol_p ? SYNTAX (c) : Ssymbol;
2562}
2434 2563
2435static Lisp_Object 2564static Lisp_Object
2436scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag) 2565scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
@@ -2441,7 +2570,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2441 int stringterm; 2570 int stringterm;
2442 bool quoted; 2571 bool quoted;
2443 bool mathexit = 0; 2572 bool mathexit = 0;
2444 enum syntaxcode code, temp_code, c_code; 2573 enum syntaxcode code;
2445 EMACS_INT min_depth = depth; /* Err out if depth gets less than this. */ 2574 EMACS_INT min_depth = depth; /* Err out if depth gets less than this. */
2446 int comstyle = 0; /* style of comment encountered */ 2575 int comstyle = 0; /* style of comment encountered */
2447 bool comnested = 0; /* whether the comment is nestable or not */ 2576 bool comnested = 0; /* whether the comment is nestable or not */
@@ -2473,7 +2602,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2473 UPDATE_SYNTAX_TABLE_FORWARD (from); 2602 UPDATE_SYNTAX_TABLE_FORWARD (from);
2474 c = FETCH_CHAR_AS_MULTIBYTE (from_byte); 2603 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2475 syntax = SYNTAX_WITH_FLAGS (c); 2604 syntax = SYNTAX_WITH_FLAGS (c);
2476 code = SYNTAX_WITH_MULTIBYTE_CHECK (c); 2605 code = syntax_multibyte (c, multibyte_symbol_p);
2477 comstart_first = SYNTAX_FLAGS_COMSTART_FIRST (syntax); 2606 comstart_first = SYNTAX_FLAGS_COMSTART_FIRST (syntax);
2478 comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax); 2607 comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax);
2479 comstyle = SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0); 2608 comstyle = SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0);
@@ -2519,10 +2648,8 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2519 { 2648 {
2520 UPDATE_SYNTAX_TABLE_FORWARD (from); 2649 UPDATE_SYNTAX_TABLE_FORWARD (from);
2521 2650
2522 /* Some compilers can't handle this inside the switch. */
2523 c = FETCH_CHAR_AS_MULTIBYTE (from_byte); 2651 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2524 c_code = SYNTAX_WITH_MULTIBYTE_CHECK (c); 2652 switch (syntax_multibyte (c, multibyte_symbol_p))
2525 switch (c_code)
2526 { 2653 {
2527 case Scharquote: 2654 case Scharquote:
2528 case Sescape: 2655 case Sescape:
@@ -2594,18 +2721,17 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2594 stringterm = FETCH_CHAR_AS_MULTIBYTE (temp_pos); 2721 stringterm = FETCH_CHAR_AS_MULTIBYTE (temp_pos);
2595 while (1) 2722 while (1)
2596 { 2723 {
2724 enum syntaxcode c_code;
2597 if (from >= stop) 2725 if (from >= stop)
2598 goto lose; 2726 goto lose;
2599 UPDATE_SYNTAX_TABLE_FORWARD (from); 2727 UPDATE_SYNTAX_TABLE_FORWARD (from);
2600 c = FETCH_CHAR_AS_MULTIBYTE (from_byte); 2728 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2729 c_code = syntax_multibyte (c, multibyte_symbol_p);
2601 if (code == Sstring 2730 if (code == Sstring
2602 ? (c == stringterm 2731 ? c == stringterm && c_code == Sstring
2603 && SYNTAX_WITH_MULTIBYTE_CHECK (c) == Sstring) 2732 : c_code == Sstring_fence)
2604 : SYNTAX_WITH_MULTIBYTE_CHECK (c) == Sstring_fence)
2605 break; 2733 break;
2606 2734
2607 /* Some compilers can't handle this inside the switch. */
2608 c_code = SYNTAX_WITH_MULTIBYTE_CHECK (c);
2609 switch (c_code) 2735 switch (c_code)
2610 { 2736 {
2611 case Scharquote: 2737 case Scharquote:
@@ -2644,7 +2770,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2644 UPDATE_SYNTAX_TABLE_BACKWARD (from); 2770 UPDATE_SYNTAX_TABLE_BACKWARD (from);
2645 c = FETCH_CHAR_AS_MULTIBYTE (from_byte); 2771 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2646 syntax= SYNTAX_WITH_FLAGS (c); 2772 syntax= SYNTAX_WITH_FLAGS (c);
2647 code = SYNTAX_WITH_MULTIBYTE_CHECK (c); 2773 code = syntax_multibyte (c, multibyte_symbol_p);
2648 if (depth == min_depth) 2774 if (depth == min_depth)
2649 last_good = from; 2775 last_good = from;
2650 comstyle = 0; 2776 comstyle = 0;
@@ -2697,9 +2823,8 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2697 temp_pos--; 2823 temp_pos--;
2698 UPDATE_SYNTAX_TABLE_BACKWARD (from - 1); 2824 UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
2699 c1 = FETCH_CHAR_AS_MULTIBYTE (temp_pos); 2825 c1 = FETCH_CHAR_AS_MULTIBYTE (temp_pos);
2700 temp_code = SYNTAX_WITH_MULTIBYTE_CHECK (c1);
2701 /* Don't allow comment-end to be quoted. */ 2826 /* Don't allow comment-end to be quoted. */
2702 if (temp_code == Sendcomment) 2827 if (syntax_multibyte (c1, multibyte_symbol_p) == Sendcomment)
2703 goto done2; 2828 goto done2;
2704 quoted = char_quoted (from - 1, temp_pos); 2829 quoted = char_quoted (from - 1, temp_pos);
2705 if (quoted) 2830 if (quoted)
@@ -2709,11 +2834,12 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2709 UPDATE_SYNTAX_TABLE_BACKWARD (from - 1); 2834 UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
2710 } 2835 }
2711 c1 = FETCH_CHAR_AS_MULTIBYTE (temp_pos); 2836 c1 = FETCH_CHAR_AS_MULTIBYTE (temp_pos);
2712 temp_code = SYNTAX_WITH_MULTIBYTE_CHECK (c1); 2837 if (! quoted)
2713 if (! (quoted || temp_code == Sword 2838 switch (syntax_multibyte (c1, multibyte_symbol_p))
2714 || temp_code == Ssymbol 2839 {
2715 || temp_code == Squote)) 2840 case Sword: case Ssymbol: case Squote: break;
2716 goto done2; 2841 default: goto done2;
2842 }
2717 DEC_BOTH (from, from_byte); 2843 DEC_BOTH (from, from_byte);
2718 } 2844 }
2719 goto done2; 2845 goto done2;
@@ -2768,10 +2894,12 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2768 goto lose; 2894 goto lose;
2769 DEC_BOTH (from, from_byte); 2895 DEC_BOTH (from, from_byte);
2770 UPDATE_SYNTAX_TABLE_BACKWARD (from); 2896 UPDATE_SYNTAX_TABLE_BACKWARD (from);
2771 if (!char_quoted (from, from_byte) 2897 if (!char_quoted (from, from_byte))
2772 && (c = FETCH_CHAR_AS_MULTIBYTE (from_byte), 2898 {
2773 SYNTAX_WITH_MULTIBYTE_CHECK (c) == code)) 2899 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2774 break; 2900 if (syntax_multibyte (c, multibyte_symbol_p) == code)
2901 break;
2902 }
2775 } 2903 }
2776 if (code == Sstring_fence && !depth && sexpflag) goto done2; 2904 if (code == Sstring_fence && !depth && sexpflag) goto done2;
2777 break; 2905 break;
@@ -2784,11 +2912,14 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2784 goto lose; 2912 goto lose;
2785 DEC_BOTH (from, from_byte); 2913 DEC_BOTH (from, from_byte);
2786 UPDATE_SYNTAX_TABLE_BACKWARD (from); 2914 UPDATE_SYNTAX_TABLE_BACKWARD (from);
2787 if (!char_quoted (from, from_byte) 2915 if (!char_quoted (from, from_byte))
2788 && (stringterm 2916 {
2789 == (c = FETCH_CHAR_AS_MULTIBYTE (from_byte))) 2917 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2790 && SYNTAX_WITH_MULTIBYTE_CHECK (c) == Sstring) 2918 if (c == stringterm
2791 break; 2919 && (syntax_multibyte (c, multibyte_symbol_p)
2920 == Sstring))
2921 break;
2922 }
2792 } 2923 }
2793 if (!depth && sexpflag) goto done2; 2924 if (!depth && sexpflag) goto done2;
2794 break; 2925 break;
@@ -2894,7 +3025,7 @@ This includes chars with "quote" or "prefix" syntax (' or p). */)
2894 while (!char_quoted (pos, pos_byte) 3025 while (!char_quoted (pos, pos_byte)
2895 /* Previous statement updates syntax table. */ 3026 /* Previous statement updates syntax table. */
2896 && ((c = FETCH_CHAR_AS_MULTIBYTE (pos_byte), SYNTAX (c) == Squote) 3027 && ((c = FETCH_CHAR_AS_MULTIBYTE (pos_byte), SYNTAX (c) == Squote)
2897 || SYNTAX_PREFIX (c))) 3028 || syntax_prefix_flag_p (c)))
2898 { 3029 {
2899 opoint = pos; 3030 opoint = pos;
2900 opoint_byte = pos_byte; 3031 opoint_byte = pos_byte;
@@ -3117,10 +3248,8 @@ do { prev_from = from; \
3117 symstarted: 3248 symstarted:
3118 while (from < end) 3249 while (from < end)
3119 { 3250 {
3120 /* Some compilers can't handle this inside the switch. */
3121 int symchar = FETCH_CHAR_AS_MULTIBYTE (from_byte); 3251 int symchar = FETCH_CHAR_AS_MULTIBYTE (from_byte);
3122 enum syntaxcode symcharcode = SYNTAX (symchar); 3252 switch (SYNTAX (symchar))
3123 switch (symcharcode)
3124 { 3253 {
3125 case Scharquote: 3254 case Scharquote:
3126 case Sescape: 3255 case Sescape:
@@ -3206,7 +3335,6 @@ do { prev_from = from; \
3206 3335
3207 if (from >= end) goto done; 3336 if (from >= end) goto done;
3208 c = FETCH_CHAR_AS_MULTIBYTE (from_byte); 3337 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
3209 /* Some compilers can't handle this inside the switch. */
3210 c_code = SYNTAX (c); 3338 c_code = SYNTAX (c);
3211 3339
3212 /* Check C_CODE here so that if the char has 3340 /* Check C_CODE here so that if the char has
diff --git a/src/syntax.h b/src/syntax.h
index 58d39b9059c..1b96284af42 100644
--- a/src/syntax.h
+++ b/src/syntax.h
@@ -18,6 +18,10 @@ GNU General Public License for more details.
18You should have received a copy of the GNU General Public License 18You should have received a copy of the GNU General Public License
19along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ 19along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 20
21INLINE_HEADER_BEGIN
22#ifndef SYNTAX_INLINE
23# define SYNTAX_INLINE INLINE
24#endif
21 25
22extern void update_syntax_table (ptrdiff_t, EMACS_INT, bool, Lisp_Object); 26extern void update_syntax_table (ptrdiff_t, EMACS_INT, bool, Lisp_Object);
23 27
@@ -54,79 +58,64 @@ enum syntaxcode
54 Smax /* Upper bound on codes that are meaningful */ 58 Smax /* Upper bound on codes that are meaningful */
55 }; 59 };
56 60
57/* Set the syntax entry VAL for char C in table TABLE. */
58
59#define SET_RAW_SYNTAX_ENTRY(table, c, val) \
60 CHAR_TABLE_SET ((table), c, (val))
61 61
62/* Set the syntax entry VAL for char-range RANGE in table TABLE. 62struct gl_state_s
63 RANGE is a cons (FROM . TO) specifying the range of characters. */ 63{
64 Lisp_Object object; /* The object we are scanning. */
65 ptrdiff_t start; /* Where to stop. */
66 ptrdiff_t stop; /* Where to stop. */
67 bool use_global; /* Whether to use global_code
68 or c_s_t. */
69 Lisp_Object global_code; /* Syntax code of current char. */
70 Lisp_Object current_syntax_table; /* Syntax table for current pos. */
71 Lisp_Object old_prop; /* Syntax-table prop at prev pos. */
72 ptrdiff_t b_property; /* First index where c_s_t is valid. */
73 ptrdiff_t e_property; /* First index where c_s_t is
74 not valid. */
75 INTERVAL forward_i; /* Where to start lookup on forward */
76 INTERVAL backward_i; /* or backward movement. The
77 data in c_s_t is valid
78 between these intervals,
79 and possibly at the
80 intervals too, depending
81 on: */
82 /* Offset for positions specified to UPDATE_SYNTAX_TABLE. */
83 ptrdiff_t offset;
84};
64 85
65#define SET_RAW_SYNTAX_ENTRY_RANGE(table, range, val) \ 86extern struct gl_state_s gl_state;
66 Fset_char_table_range ((table), (range), (val))
67 87
68/* SYNTAX_ENTRY fetches the information from the entry for character C 88/* Fetch the information from the entry for character C
69 in syntax table TABLE, or from globally kept data (gl_state). 89 in syntax table TABLE, or from globally kept data (gl_state).
70 Does inheritance. */ 90 Does inheritance. */
71/* CURRENT_SYNTAX_TABLE gives the syntax table valid for current
72 position, it is either the buffer's syntax table, or syntax table
73 found in text properties. */
74 91
92SYNTAX_INLINE Lisp_Object
93SYNTAX_ENTRY (int c)
94{
75#ifdef SYNTAX_ENTRY_VIA_PROPERTY 95#ifdef SYNTAX_ENTRY_VIA_PROPERTY
76# define SYNTAX_ENTRY(c) \ 96 return (gl_state.use_global
77 (gl_state.use_global ? gl_state.global_code : SYNTAX_ENTRY_INT (c)) 97 ? gl_state.global_code
78# define CURRENT_SYNTAX_TABLE gl_state.current_syntax_table 98 : CHAR_TABLE_REF (gl_state.current_syntax_table, c));
79#else 99#else
80# define SYNTAX_ENTRY SYNTAX_ENTRY_INT 100 return CHAR_TABLE_REF (BVAR (current_buffer, syntax_table), c);
81# define CURRENT_SYNTAX_TABLE BVAR (current_buffer, syntax_table)
82#endif 101#endif
83 102}
84#define SYNTAX_ENTRY_INT(c) CHAR_TABLE_REF (CURRENT_SYNTAX_TABLE, (c))
85 103
86/* Extract the information from the entry for character C 104/* Extract the information from the entry for character C
87 in the current syntax table. */ 105 in the current syntax table. */
88 106
89#ifdef __GNUC__ 107SYNTAX_INLINE int
90#define SYNTAX(c) \ 108SYNTAX_WITH_FLAGS (int c)
91 ({ Lisp_Object _syntax_temp; \ 109{
92 _syntax_temp = SYNTAX_ENTRY (c); \ 110 Lisp_Object ent = SYNTAX_ENTRY (c);
93 (CONSP (_syntax_temp) \ 111 return CONSP (ent) ? XINT (XCAR (ent)) : Swhitespace;
94 ? (enum syntaxcode) (XINT (XCAR (_syntax_temp)) & 0xff) \ 112}
95 : Swhitespace); }) 113
96 114SYNTAX_INLINE enum syntaxcode
97#define SYNTAX_WITH_FLAGS(c) \ 115SYNTAX (int c)
98 ({ Lisp_Object _syntax_temp; \ 116{
99 _syntax_temp = SYNTAX_ENTRY (c); \ 117 return SYNTAX_WITH_FLAGS (c) & 0xff;
100 (CONSP (_syntax_temp) \ 118}
101 ? XINT (XCAR (_syntax_temp)) \
102 : Swhitespace); })
103
104#define SYNTAX_MATCH(c) \
105 ({ Lisp_Object _syntax_temp; \
106 _syntax_temp = SYNTAX_ENTRY (c); \
107 (CONSP (_syntax_temp) \
108 ? XCDR (_syntax_temp) \
109 : Qnil); })
110#else
111extern Lisp_Object syntax_temp;
112#define SYNTAX(c) \
113 (syntax_temp = SYNTAX_ENTRY ((c)), \
114 (CONSP (syntax_temp) \
115 ? (enum syntaxcode) (XINT (XCAR (syntax_temp)) & 0xff) \
116 : Swhitespace))
117
118#define SYNTAX_WITH_FLAGS(c) \
119 (syntax_temp = SYNTAX_ENTRY ((c)), \
120 (CONSP (syntax_temp) \
121 ? XINT (XCAR (syntax_temp)) \
122 : Swhitespace))
123
124#define SYNTAX_MATCH(c) \
125 (syntax_temp = SYNTAX_ENTRY ((c)), \
126 (CONSP (syntax_temp) \
127 ? XCDR (syntax_temp) \
128 : Qnil))
129#endif
130 119
131 120
132/* Whether the syntax of the character C has the prefix flag set. */ 121/* Whether the syntax of the character C has the prefix flag set. */
@@ -145,158 +134,65 @@ extern char const syntax_code_spec[16];
145/* Convert the byte offset BYTEPOS into a character position, 134/* Convert the byte offset BYTEPOS into a character position,
146 for the object recorded in gl_state with SETUP_SYNTAX_TABLE_FOR_OBJECT. 135 for the object recorded in gl_state with SETUP_SYNTAX_TABLE_FOR_OBJECT.
147 136
148 The value is meant for use in the UPDATE_SYNTAX_TABLE... macros. 137 The value is meant for use in code that does nothing when
149 These macros do nothing when parse_sexp_lookup_properties is 0, 138 parse_sexp_lookup_properties is 0, so return 0 in that case, for speed. */
150 so we return 0 in that case, for speed. */ 139
151 140SYNTAX_INLINE ptrdiff_t
152#define SYNTAX_TABLE_BYTE_TO_CHAR(bytepos) \ 141SYNTAX_TABLE_BYTE_TO_CHAR (ptrdiff_t bytepos)
153 (! parse_sexp_lookup_properties \ 142{
154 ? 0 \ 143 return (! parse_sexp_lookup_properties
155 : STRINGP (gl_state.object) \ 144 ? 0
156 ? string_byte_to_char (gl_state.object, (bytepos)) \ 145 : STRINGP (gl_state.object)
157 : BUFFERP (gl_state.object) \ 146 ? string_byte_to_char (gl_state.object, bytepos)
158 ? buf_bytepos_to_charpos (XBUFFER (gl_state.object), \ 147 : BUFFERP (gl_state.object)
159 (bytepos) + BUF_BEGV_BYTE (XBUFFER (gl_state.object)) - 1) - BUF_BEGV (XBUFFER (gl_state.object)) + 1 \ 148 ? ((buf_bytepos_to_charpos
160 : NILP (gl_state.object) \ 149 (XBUFFER (gl_state.object),
161 ? BYTE_TO_CHAR ((bytepos) + BEGV_BYTE - 1) - BEGV + 1 \ 150 (bytepos + BUF_BEGV_BYTE (XBUFFER (gl_state.object)) - 1)))
162 : (bytepos)) 151 - BUF_BEGV (XBUFFER (gl_state.object)) + 1)
152 : NILP (gl_state.object)
153 ? BYTE_TO_CHAR (bytepos + BEGV_BYTE - 1) - BEGV + 1
154 : bytepos);
155}
163 156
164/* Make syntax table state (gl_state) good for CHARPOS, assuming it is 157/* Make syntax table state (gl_state) good for CHARPOS, assuming it is
165 currently good for a position before CHARPOS. */ 158 currently good for a position before CHARPOS. */
166 159
167#define UPDATE_SYNTAX_TABLE_FORWARD(charpos) \ 160SYNTAX_INLINE void
168 (parse_sexp_lookup_properties \ 161UPDATE_SYNTAX_TABLE_FORWARD (ptrdiff_t charpos)
169 && (charpos) >= gl_state.e_property \ 162{
170 ? (update_syntax_table ((charpos) + gl_state.offset, 1, 0, \ 163 if (parse_sexp_lookup_properties && charpos >= gl_state.e_property)
171 gl_state.object), \ 164 update_syntax_table (charpos + gl_state.offset, 1, 0, gl_state.object);
172 1) \ 165}
173 : 0)
174 166
175/* Make syntax table state (gl_state) good for CHARPOS, assuming it is 167/* Make syntax table state (gl_state) good for CHARPOS, assuming it is
176 currently good for a position after CHARPOS. */ 168 currently good for a position after CHARPOS. */
177 169
178#define UPDATE_SYNTAX_TABLE_BACKWARD(charpos) \ 170SYNTAX_INLINE void
179 (parse_sexp_lookup_properties \ 171UPDATE_SYNTAX_TABLE_BACKWARD (ptrdiff_t charpos)
180 && (charpos) < gl_state.b_property \ 172{
181 ? (update_syntax_table ((charpos) + gl_state.offset, -1, 0, \ 173 if (parse_sexp_lookup_properties && charpos < gl_state.b_property)
182 gl_state.object), \ 174 update_syntax_table (charpos + gl_state.offset, -1, 0, gl_state.object);
183 1) \ 175}
184 : 0)
185 176
186/* Make syntax table good for CHARPOS. */ 177/* Make syntax table good for CHARPOS. */
187 178
188#define UPDATE_SYNTAX_TABLE(charpos) \ 179SYNTAX_INLINE void
189 (parse_sexp_lookup_properties \ 180UPDATE_SYNTAX_TABLE (ptrdiff_t charpos)
190 && (charpos) < gl_state.b_property \ 181{
191 ? (update_syntax_table ((charpos) + gl_state.offset, -1, 0, \ 182 UPDATE_SYNTAX_TABLE_BACKWARD (charpos);
192 gl_state.object), \ 183 UPDATE_SYNTAX_TABLE_FORWARD (charpos);
193 1) \ 184}
194 : (parse_sexp_lookup_properties \ 185
195 && (charpos) >= gl_state.e_property \ 186/* Set up the buffer-global syntax table. */
196 ? (update_syntax_table ((charpos) + gl_state.offset, 1, 0,\
197 gl_state.object), \
198 1) \
199 : 0))
200
201/* This macro sets up the buffer-global syntax table. */
202#define SETUP_BUFFER_SYNTAX_TABLE() \
203do \
204 { \
205 gl_state.use_global = 0; \
206 gl_state.current_syntax_table = BVAR (current_buffer, syntax_table);\
207 } while (0)
208
209/* This macro should be called with FROM at the start of forward
210 search, or after the last position of the backward search. It
211 makes sure that the first char is picked up with correct table, so
212 one does not need to call UPDATE_SYNTAX_TABLE immediately after the
213 call.
214 Sign of COUNT gives the direction of the search.
215 */
216
217#define SETUP_SYNTAX_TABLE(FROM, COUNT) \
218do \
219 { \
220 SETUP_BUFFER_SYNTAX_TABLE (); \
221 gl_state.b_property = BEGV; \
222 gl_state.e_property = ZV + 1; \
223 gl_state.object = Qnil; \
224 gl_state.offset = 0; \
225 if (parse_sexp_lookup_properties) \
226 if ((COUNT) > 0 || (FROM) > BEGV) \
227 update_syntax_table ((COUNT) > 0 ? (FROM) : (FROM) - 1, (COUNT),\
228 1, Qnil); \
229 } \
230while (0)
231
232/* Same as above, but in OBJECT. If OBJECT is nil, use current buffer.
233 If it is t (which is only used in fast_c_string_match_ignore_case),
234 ignore properties altogether.
235
236 This is meant for regex.c to use. For buffers, regex.c passes arguments
237 to the UPDATE_SYNTAX_TABLE macros which are relative to BEGV.
238 So if it is a buffer, we set the offset field to BEGV. */
239
240#define SETUP_SYNTAX_TABLE_FOR_OBJECT(OBJECT, FROM, COUNT) \
241do \
242 { \
243 SETUP_BUFFER_SYNTAX_TABLE (); \
244 gl_state.object = (OBJECT); \
245 if (BUFFERP (gl_state.object)) \
246 { \
247 struct buffer *buf = XBUFFER (gl_state.object); \
248 gl_state.b_property = 1; \
249 gl_state.e_property = BUF_ZV (buf) - BUF_BEGV (buf) + 1; \
250 gl_state.offset = BUF_BEGV (buf) - 1; \
251 } \
252 else if (NILP (gl_state.object)) \
253 { \
254 gl_state.b_property = 1; \
255 gl_state.e_property = ZV - BEGV + 1; \
256 gl_state.offset = BEGV - 1; \
257 } \
258 else if (EQ (gl_state.object, Qt)) \
259 { \
260 gl_state.b_property = 0; \
261 gl_state.e_property = PTRDIFF_MAX; \
262 gl_state.offset = 0; \
263 } \
264 else \
265 { \
266 gl_state.b_property = 0; \
267 gl_state.e_property = 1 + SCHARS (gl_state.object); \
268 gl_state.offset = 0; \
269 } \
270 if (parse_sexp_lookup_properties) \
271 update_syntax_table (((FROM) + gl_state.offset \
272 + (COUNT > 0 ? 0 : -1)), \
273 COUNT, 1, gl_state.object); \
274 } \
275while (0)
276 187
277struct gl_state_s 188SYNTAX_INLINE void
189SETUP_BUFFER_SYNTAX_TABLE (void)
278{ 190{
279 Lisp_Object object; /* The object we are scanning. */ 191 gl_state.use_global = 0;
280 ptrdiff_t start; /* Where to stop. */ 192 gl_state.current_syntax_table = BVAR (current_buffer, syntax_table);
281 ptrdiff_t stop; /* Where to stop. */ 193}
282 int use_global; /* Whether to use global_code
283 or c_s_t. */
284 Lisp_Object global_code; /* Syntax code of current char. */
285 Lisp_Object current_syntax_table; /* Syntax table for current pos. */
286 Lisp_Object old_prop; /* Syntax-table prop at prev pos. */
287 ptrdiff_t b_property; /* First index where c_s_t is valid. */
288 ptrdiff_t e_property; /* First index where c_s_t is
289 not valid. */
290 INTERVAL forward_i; /* Where to start lookup on forward */
291 INTERVAL backward_i; /* or backward movement. The
292 data in c_s_t is valid
293 between these intervals,
294 and possibly at the
295 intervals too, depending
296 on: */
297 /* Offset for positions specified to UPDATE_SYNTAX_TABLE. */
298 ptrdiff_t offset;
299};
300 194
301extern struct gl_state_s gl_state;
302extern ptrdiff_t scan_words (ptrdiff_t, EMACS_INT); 195extern ptrdiff_t scan_words (ptrdiff_t, EMACS_INT);
196extern void SETUP_SYNTAX_TABLE_FOR_OBJECT (Lisp_Object, ptrdiff_t, ptrdiff_t);
197
198INLINE_HEADER_END
diff --git a/src/sysdep.c b/src/sysdep.c
index 212ceef64b9..f614d8bc557 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -22,7 +22,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22#define SYSTIME_INLINE EXTERN_INLINE 22#define SYSTIME_INLINE EXTERN_INLINE
23 23
24#include <execinfo.h> 24#include <execinfo.h>
25#include <stdio.h> 25#include "sysstdio.h"
26#ifdef HAVE_PWD_H 26#ifdef HAVE_PWD_H
27#include <pwd.h> 27#include <pwd.h>
28#include <grp.h> 28#include <grp.h>
@@ -31,7 +31,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
31#include <unistd.h> 31#include <unistd.h>
32 32
33#include <c-ctype.h> 33#include <c-ctype.h>
34#include <ignore-value.h>
35#include <utimens.h> 34#include <utimens.h>
36 35
37#include "lisp.h" 36#include "lisp.h"
@@ -103,8 +102,8 @@ int _cdecl _getpid (void);
103#include "syssignal.h" 102#include "syssignal.h"
104#include "systime.h" 103#include "systime.h"
105 104
106static int emacs_get_tty (int, struct emacs_tty *); 105static void emacs_get_tty (int, struct emacs_tty *);
107static int emacs_set_tty (int, struct emacs_tty *, int); 106static int emacs_set_tty (int, struct emacs_tty *, bool);
108 107
109/* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781. */ 108/* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781. */
110#ifndef ULLONG_MAX 109#ifndef ULLONG_MAX
@@ -538,13 +537,11 @@ sys_subshell (void)
538 if (str && chdir ((char *) str) != 0) 537 if (str && chdir ((char *) str) != 0)
539 { 538 {
540#ifndef DOS_NT 539#ifndef DOS_NT
541 ignore_value (write (1, "Can't chdir\n", 12)); 540 emacs_perror ((char *) str);
542 _exit (1); 541 _exit (EXIT_CANCELED);
543#endif 542#endif
544 } 543 }
545 544
546 close_process_descs (); /* Close Emacs's pipes/ptys */
547
548#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */ 545#ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */
549 { 546 {
550 char *epwd = getenv ("PWD"); 547 char *epwd = getenv ("PWD");
@@ -572,8 +569,8 @@ sys_subshell (void)
572 write (1, "Can't execute subshell", 22); 569 write (1, "Can't execute subshell", 22);
573#else /* not WINDOWSNT */ 570#else /* not WINDOWSNT */
574 execlp (sh, sh, (char *) 0); 571 execlp (sh, sh, (char *) 0);
575 ignore_value (write (1, "Can't execute subshell", 22)); 572 emacs_perror (sh);
576 _exit (1); 573 _exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
577#endif /* not WINDOWSNT */ 574#endif /* not WINDOWSNT */
578#endif /* not MSDOS */ 575#endif /* not MSDOS */
579 } 576 }
@@ -772,31 +769,26 @@ widen_foreground_group (int fd)
772 769
773/* Getting and setting emacs_tty structures. */ 770/* Getting and setting emacs_tty structures. */
774 771
775/* Set *TC to the parameters associated with the terminal FD. 772/* Set *TC to the parameters associated with the terminal FD,
776 Return zero if all's well, or -1 if we ran into an error we 773 or clear it if the parameters are not available. */
777 couldn't deal with. */ 774static void
778int
779emacs_get_tty (int fd, struct emacs_tty *settings) 775emacs_get_tty (int fd, struct emacs_tty *settings)
780{ 776{
781 /* Retrieve the primary parameters - baud rate, character size, etcetera. */ 777 /* Retrieve the primary parameters - baud rate, character size, etcetera. */
782#ifndef DOS_NT 778#ifndef DOS_NT
783 /* We have those nifty POSIX tcmumbleattr functions. */ 779 /* We have those nifty POSIX tcmumbleattr functions. */
784 memset (&settings->main, 0, sizeof (settings->main)); 780 memset (&settings->main, 0, sizeof (settings->main));
785 if (tcgetattr (fd, &settings->main) < 0) 781 tcgetattr (fd, &settings->main);
786 return -1;
787#endif 782#endif
788
789 /* We have survived the tempest. */
790 return 0;
791} 783}
792 784
793 785
794/* Set the parameters of the tty on FD according to the contents of 786/* Set the parameters of the tty on FD according to the contents of
795 *SETTINGS. If FLUSHP is non-zero, we discard input. 787 *SETTINGS. If FLUSHP, discard input.
796 Return 0 if all went well, and -1 if anything failed. */ 788 Return 0 if all went well, and -1 (setting errno) if anything failed. */
797 789
798int 790static int
799emacs_set_tty (int fd, struct emacs_tty *settings, int flushp) 791emacs_set_tty (int fd, struct emacs_tty *settings, bool flushp)
800{ 792{
801 /* Set the primary parameters - baud rate, character size, etcetera. */ 793 /* Set the primary parameters - baud rate, character size, etcetera. */
802#ifndef DOS_NT 794#ifndef DOS_NT
@@ -1121,10 +1113,10 @@ init_sys_modes (struct tty_display_info *tty_out)
1121 tty_out->term_initted = 1; 1113 tty_out->term_initted = 1;
1122} 1114}
1123 1115
1124/* Return nonzero if safe to use tabs in output. 1116/* Return true if safe to use tabs in output.
1125 At the time this is called, init_sys_modes has not been done yet. */ 1117 At the time this is called, init_sys_modes has not been done yet. */
1126 1118
1127int 1119bool
1128tabs_safe_p (int fd) 1120tabs_safe_p (int fd)
1129{ 1121{
1130 struct emacs_tty etty; 1122 struct emacs_tty etty;
@@ -1378,8 +1370,10 @@ init_system_name (void)
1378 uname (&uts); 1370 uname (&uts);
1379 Vsystem_name = build_string (uts.nodename); 1371 Vsystem_name = build_string (uts.nodename);
1380#else /* HAVE_GETHOSTNAME */ 1372#else /* HAVE_GETHOSTNAME */
1381 unsigned int hostname_size = 256; 1373 char *hostname_alloc = NULL;
1382 char *hostname = alloca (hostname_size); 1374 char hostname_buf[256];
1375 ptrdiff_t hostname_size = sizeof hostname_buf;
1376 char *hostname = hostname_buf;
1383 1377
1384 /* Try to get the host name; if the buffer is too short, try 1378 /* Try to get the host name; if the buffer is too short, try
1385 again. Apparently, the only indication gethostname gives of 1379 again. Apparently, the only indication gethostname gives of
@@ -1394,8 +1388,8 @@ init_system_name (void)
1394 if (strlen (hostname) < hostname_size - 1) 1388 if (strlen (hostname) < hostname_size - 1)
1395 break; 1389 break;
1396 1390
1397 hostname_size <<= 1; 1391 hostname = hostname_alloc = xpalloc (hostname_alloc, &hostname_size, 1,
1398 hostname = alloca (hostname_size); 1392 min (PTRDIFF_MAX, SIZE_MAX), 1);
1399 } 1393 }
1400#ifdef HAVE_SOCKETS 1394#ifdef HAVE_SOCKETS
1401 /* Turn the hostname into the official, fully-qualified hostname. 1395 /* Turn the hostname into the official, fully-qualified hostname.
@@ -1440,7 +1434,13 @@ init_system_name (void)
1440 } 1434 }
1441 if (it) 1435 if (it)
1442 { 1436 {
1443 hostname = alloca (strlen (it->ai_canonname) + 1); 1437 ptrdiff_t len = strlen (it->ai_canonname);
1438 if (hostname_size <= len)
1439 {
1440 hostname_size = len + 1;
1441 hostname = hostname_alloc = xrealloc (hostname_alloc,
1442 hostname_size);
1443 }
1444 strcpy (hostname, it->ai_canonname); 1444 strcpy (hostname, it->ai_canonname);
1445 } 1445 }
1446 freeaddrinfo (res); 1446 freeaddrinfo (res);
@@ -1487,10 +1487,11 @@ init_system_name (void)
1487 } 1487 }
1488#endif /* HAVE_SOCKETS */ 1488#endif /* HAVE_SOCKETS */
1489 Vsystem_name = build_string (hostname); 1489 Vsystem_name = build_string (hostname);
1490 xfree (hostname_alloc);
1490#endif /* HAVE_GETHOSTNAME */ 1491#endif /* HAVE_GETHOSTNAME */
1491 { 1492 {
1492 unsigned char *p; 1493 char *p;
1493 for (p = SDATA (Vsystem_name); *p; p++) 1494 for (p = SSDATA (Vsystem_name); *p; p++)
1494 if (*p == ' ' || *p == '\t') 1495 if (*p == ' ' || *p == '\t')
1495 *p = '-'; 1496 *p = '-';
1496 } 1497 }
@@ -1630,7 +1631,7 @@ deliver_thread_signal (int sig, signal_handler_t handler)
1630# undef sys_siglist 1631# undef sys_siglist
1631# ifdef _sys_siglist 1632# ifdef _sys_siglist
1632# define sys_siglist _sys_siglist 1633# define sys_siglist _sys_siglist
1633# elif defined HAVE_DECL___SYS_SIGLIST 1634# elif HAVE_DECL___SYS_SIGLIST
1634# define sys_siglist __sys_siglist 1635# define sys_siglist __sys_siglist
1635# else 1636# else
1636# define sys_siglist my_sys_siglist 1637# define sys_siglist my_sys_siglist
@@ -2136,10 +2137,10 @@ emacs_backtrace (int backtrace_limit)
2136 2137
2137 if (npointers) 2138 if (npointers)
2138 { 2139 {
2139 ignore_value (write (STDERR_FILENO, "\nBacktrace:\n", 12)); 2140 emacs_write (STDERR_FILENO, "\nBacktrace:\n", 12);
2140 backtrace_symbols_fd (buffer, npointers, STDERR_FILENO); 2141 backtrace_symbols_fd (buffer, npointers, STDERR_FILENO);
2141 if (bounded_limit < npointers) 2142 if (bounded_limit < npointers)
2142 ignore_value (write (STDERR_FILENO, "...\n", 4)); 2143 emacs_write (STDERR_FILENO, "...\n", 4);
2143 } 2144 }
2144} 2145}
2145 2146
@@ -2151,34 +2152,108 @@ emacs_abort (void)
2151} 2152}
2152#endif 2153#endif
2153 2154
2155/* Open FILE for Emacs use, using open flags OFLAG and mode MODE.
2156 Arrange for subprograms to not inherit the file descriptor.
2157 Prefer a method that is multithread-safe, if available.
2158 Do not fail merely because the open was interrupted by a signal.
2159 Allow the user to quit. */
2160
2154int 2161int
2155emacs_open (const char *path, int oflag, int mode) 2162emacs_open (const char *file, int oflags, int mode)
2156{ 2163{
2157 register int rtnval; 2164 int fd;
2158 2165 oflags |= O_CLOEXEC;
2159 while ((rtnval = open (path, oflag, mode)) == -1 2166 while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR)
2160 && (errno == EINTR))
2161 QUIT; 2167 QUIT;
2162 return (rtnval); 2168 if (! O_CLOEXEC && 0 <= fd)
2169 fcntl (fd, F_SETFD, FD_CLOEXEC);
2170 return fd;
2163} 2171}
2164 2172
2165int 2173/* Open FILE as a stream for Emacs use, with mode MODE.
2166emacs_close (int fd) 2174 Act like emacs_open with respect to threads, signals, and quits. */
2175
2176FILE *
2177emacs_fopen (char const *file, char const *mode)
2167{ 2178{
2168 int did_retry = 0; 2179 int fd, omode, oflags;
2169 register int rtnval; 2180 int bflag = 0;
2181 char const *m = mode;
2170 2182
2171 while ((rtnval = close (fd)) == -1 2183 switch (*m++)
2172 && (errno == EINTR)) 2184 {
2173 did_retry = 1; 2185 case 'r': omode = O_RDONLY; oflags = 0; break;
2186 case 'w': omode = O_WRONLY; oflags = O_CREAT | O_TRUNC; break;
2187 case 'a': omode = O_WRONLY; oflags = O_CREAT | O_APPEND; break;
2188 default: emacs_abort ();
2189 }
2174 2190
2175 /* If close is interrupted SunOS 4.1 may or may not have closed the 2191 while (*m)
2176 file descriptor. If it did the second close will fail with 2192 switch (*m++)
2177 errno = EBADF. That means we have succeeded. */ 2193 {
2178 if (rtnval == -1 && did_retry && errno == EBADF) 2194 case '+': omode = O_RDWR; break;
2179 return 0; 2195 case 'b': bflag = O_BINARY; break;
2196 case 't': bflag = O_TEXT; break;
2197 default: /* Ignore. */ break;
2198 }
2199
2200 fd = emacs_open (file, omode | oflags | bflag, 0666);
2201 return fd < 0 ? 0 : fdopen (fd, mode);
2202}
2203
2204/* Approximate posix_close and POSIX_CLOSE_RESTART well enough for Emacs.
2205 For the background behind this mess, please see Austin Group defect 529
2206 <http://austingroupbugs.net/view.php?id=529>. */
2207
2208#ifndef POSIX_CLOSE_RESTART
2209# define POSIX_CLOSE_RESTART 1
2210static int
2211posix_close (int fd, int flag)
2212{
2213 /* Only the POSIX_CLOSE_RESTART case is emulated. */
2214 eassert (flag == POSIX_CLOSE_RESTART);
2180 2215
2181 return rtnval; 2216 /* Things are tricky if close (fd) returns -1 with errno == EINTR
2217 on a system that does not define POSIX_CLOSE_RESTART.
2218
2219 In this case, in some systems (e.g., GNU/Linux, AIX) FD is
2220 closed, and retrying the close could inadvertently close a file
2221 descriptor allocated by some other thread. In other systems
2222 (e.g., HP/UX) FD is not closed. And in still other systems
2223 (e.g., OS X, Solaris), maybe FD is closed, maybe not, and in a
2224 multithreaded program there can be no way to tell.
2225
2226 So, in this case, pretend that the close succeeded. This works
2227 well on systems like GNU/Linux that close FD. Although it may
2228 leak a file descriptor on other systems, the leak is unlikely and
2229 it's better to leak than to close a random victim. */
2230 return close (fd) == 0 || errno == EINTR ? 0 : -1;
2231}
2232#endif
2233
2234/* Close FD, retrying if interrupted. If successful, return 0;
2235 otherwise, return -1 and set errno to a non-EINTR value. Consider
2236 an EINPROGRESS error to be successful, as that's merely a signal
2237 arriving. FD is always closed when this function returns, even
2238 when it returns -1.
2239
2240 Do not call this function if FD is nonnegative and might already be closed,
2241 as that might close an innocent victim opened by some other thread. */
2242
2243int
2244emacs_close (int fd)
2245{
2246 while (1)
2247 {
2248 int r = posix_close (fd, POSIX_CLOSE_RESTART);
2249 if (r == 0)
2250 return r;
2251 if (!POSIX_CLOSE_RESTART || errno != EINTR)
2252 {
2253 eassert (errno != EBADF || fd < 0);
2254 return errno == EINPROGRESS ? 0 : r;
2255 }
2256 }
2182} 2257}
2183 2258
2184/* Maximum number of bytes to read or write in a single system call. 2259/* Maximum number of bytes to read or write in a single system call.
@@ -2210,27 +2285,26 @@ emacs_read (int fildes, char *buf, ptrdiff_t nbyte)
2210} 2285}
2211 2286
2212/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if interrupted 2287/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if interrupted
2213 or if a partial write occurs. Return the number of bytes written, setting 2288 or if a partial write occurs. If interrupted, process pending
2289 signals if PROCESS SIGNALS. Return the number of bytes written, setting
2214 errno if this is less than NBYTE. */ 2290 errno if this is less than NBYTE. */
2215ptrdiff_t 2291static ptrdiff_t
2216emacs_write (int fildes, const char *buf, ptrdiff_t nbyte) 2292emacs_full_write (int fildes, char const *buf, ptrdiff_t nbyte,
2293 bool process_signals)
2217{ 2294{
2218 ssize_t rtnval; 2295 ptrdiff_t bytes_written = 0;
2219 ptrdiff_t bytes_written;
2220
2221 bytes_written = 0;
2222 2296
2223 while (nbyte > 0) 2297 while (nbyte > 0)
2224 { 2298 {
2225 rtnval = write (fildes, buf, min (nbyte, MAX_RW_COUNT)); 2299 ssize_t n = write (fildes, buf, min (nbyte, MAX_RW_COUNT));
2226 2300
2227 if (rtnval < 0) 2301 if (n < 0)
2228 { 2302 {
2229 if (errno == EINTR) 2303 if (errno == EINTR)
2230 { 2304 {
2231 /* I originally used `QUIT' but that might causes files to 2305 /* I originally used `QUIT' but that might causes files to
2232 be truncated if you hit C-g in the middle of it. --Stef */ 2306 be truncated if you hit C-g in the middle of it. --Stef */
2233 if (pending_signals) 2307 if (process_signals && pending_signals)
2234 process_pending_signals (); 2308 process_pending_signals ();
2235 continue; 2309 continue;
2236 } 2310 }
@@ -2238,12 +2312,57 @@ emacs_write (int fildes, const char *buf, ptrdiff_t nbyte)
2238 break; 2312 break;
2239 } 2313 }
2240 2314
2241 buf += rtnval; 2315 buf += n;
2242 nbyte -= rtnval; 2316 nbyte -= n;
2243 bytes_written += rtnval; 2317 bytes_written += n;
2244 } 2318 }
2245 2319
2246 return (bytes_written); 2320 return bytes_written;
2321}
2322
2323/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if
2324 interrupted or if a partial write occurs. Return the number of
2325 bytes written, setting errno if this is less than NBYTE. */
2326ptrdiff_t
2327emacs_write (int fildes, char const *buf, ptrdiff_t nbyte)
2328{
2329 return emacs_full_write (fildes, buf, nbyte, 0);
2330}
2331
2332/* Like emacs_write, but also process pending signals if interrupted. */
2333ptrdiff_t
2334emacs_write_sig (int fildes, char const *buf, ptrdiff_t nbyte)
2335{
2336 return emacs_full_write (fildes, buf, nbyte, 1);
2337}
2338
2339/* Write a diagnostic to standard error that contains MESSAGE and a
2340 string derived from errno. Preserve errno. Do not buffer stderr.
2341 Do not process pending signals if interrupted. */
2342void
2343emacs_perror (char const *message)
2344{
2345 int err = errno;
2346 char const *error_string = strerror (err);
2347 char const *command = (initial_argv && initial_argv[0]
2348 ? initial_argv[0] : "emacs");
2349 /* Write it out all at once, if it's short; this is less likely to
2350 be interleaved with other output. */
2351 char buf[BUFSIZ];
2352 int nbytes = snprintf (buf, sizeof buf, "%s: %s: %s\n",
2353 command, message, error_string);
2354 if (0 <= nbytes && nbytes < BUFSIZ)
2355 emacs_write (STDERR_FILENO, buf, nbytes);
2356 else
2357 {
2358 emacs_write (STDERR_FILENO, command, strlen (command));
2359 emacs_write (STDERR_FILENO, ": ", 2);
2360 emacs_write (STDERR_FILENO, message, strlen (message));
2361 emacs_write (STDERR_FILENO, ": ", 2);
2362 emacs_write (STDERR_FILENO, error_string, strlen (error_string));
2363 emacs_write (STDERR_FILENO, "\n", 1);
2364 }
2365 errno = err;
2247} 2366}
2248 2367
2249/* Return a struct timeval that is roughly equivalent to T. 2368/* Return a struct timeval that is roughly equivalent to T.
@@ -2597,7 +2716,7 @@ list_system_processes (void)
2597 2716
2598#endif /* !defined (WINDOWSNT) */ 2717#endif /* !defined (WINDOWSNT) */
2599 2718
2600#ifdef GNU_LINUX 2719#if defined GNU_LINUX && defined HAVE_LONG_LONG_INT
2601static EMACS_TIME 2720static EMACS_TIME
2602time_from_jiffies (unsigned long long tval, long hz) 2721time_from_jiffies (unsigned long long tval, long hz)
2603{ 2722{
@@ -2637,7 +2756,7 @@ get_up_time (void)
2637 EMACS_TIME up = make_emacs_time (0, 0); 2756 EMACS_TIME up = make_emacs_time (0, 0);
2638 2757
2639 block_input (); 2758 block_input ();
2640 fup = fopen ("/proc/uptime", "r"); 2759 fup = emacs_fopen ("/proc/uptime", "r");
2641 2760
2642 if (fup) 2761 if (fup)
2643 { 2762 {
@@ -2682,7 +2801,7 @@ procfs_ttyname (int rdev)
2682 char name[PATH_MAX]; 2801 char name[PATH_MAX];
2683 2802
2684 block_input (); 2803 block_input ();
2685 fdev = fopen ("/proc/tty/drivers", "r"); 2804 fdev = emacs_fopen ("/proc/tty/drivers", "r");
2686 2805
2687 if (fdev) 2806 if (fdev)
2688 { 2807 {
@@ -2724,7 +2843,7 @@ procfs_get_total_memory (void)
2724 unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */ 2843 unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
2725 2844
2726 block_input (); 2845 block_input ();
2727 fmem = fopen ("/proc/meminfo", "r"); 2846 fmem = emacs_fopen ("/proc/meminfo", "r");
2728 2847
2729 if (fmem) 2848 if (fmem)
2730 { 2849 {
diff --git a/src/sysstdio.h b/src/sysstdio.h
new file mode 100644
index 00000000000..e9dfb696059
--- /dev/null
+++ b/src/sysstdio.h
@@ -0,0 +1,2 @@
1#include <stdio.h>
2extern FILE *emacs_fopen (char const *, char const *);
diff --git a/src/systime.h b/src/systime.h
index c3bc00c1479..df733b290c3 100644
--- a/src/systime.h
+++ b/src/systime.h
@@ -67,7 +67,9 @@ SYSTIME_INLINE time_t *emacs_secs_addr (EMACS_TIME *t) { return &t->tv_sec; }
67SYSTIME_INLINE EMACS_TIME 67SYSTIME_INLINE EMACS_TIME
68make_emacs_time (time_t s, int ns) 68make_emacs_time (time_t s, int ns)
69{ 69{
70 EMACS_TIME r = { s, ns }; 70 EMACS_TIME r;
71 r.tv_sec = s;
72 r.tv_nsec = ns;
71 return r; 73 return r;
72} 74}
73 75
@@ -75,7 +77,9 @@ make_emacs_time (time_t s, int ns)
75SYSTIME_INLINE EMACS_TIME 77SYSTIME_INLINE EMACS_TIME
76invalid_emacs_time (void) 78invalid_emacs_time (void)
77{ 79{
78 EMACS_TIME r = { 0, -1 }; 80 EMACS_TIME r;
81 r.tv_sec = 0;
82 r.tv_nsec = -1;
79 return r; 83 return r;
80} 84}
81 85
@@ -166,21 +170,6 @@ EMACS_TIME_EQ (EMACS_TIME t1, EMACS_TIME t2)
166 return timespec_cmp (t1, t2) == 0; 170 return timespec_cmp (t1, t2) == 0;
167} 171}
168SYSTIME_INLINE int 172SYSTIME_INLINE int
169EMACS_TIME_NE (EMACS_TIME t1, EMACS_TIME t2)
170{
171 return timespec_cmp (t1, t2) != 0;
172}
173SYSTIME_INLINE int
174EMACS_TIME_GT (EMACS_TIME t1, EMACS_TIME t2)
175{
176 return timespec_cmp (t1, t2) > 0;
177}
178SYSTIME_INLINE int
179EMACS_TIME_GE (EMACS_TIME t1, EMACS_TIME t2)
180{
181 return timespec_cmp (t1, t2) >= 0;
182}
183SYSTIME_INLINE int
184EMACS_TIME_LT (EMACS_TIME t1, EMACS_TIME t2) 173EMACS_TIME_LT (EMACS_TIME t1, EMACS_TIME t2)
185{ 174{
186 return timespec_cmp (t1, t2) < 0; 175 return timespec_cmp (t1, t2) < 0;
diff --git a/src/term.c b/src/term.c
index 0bcef55947a..b6878a0abd1 100644
--- a/src/term.c
+++ b/src/term.c
@@ -71,13 +71,13 @@ static void tty_turn_off_highlight (struct tty_display_info *);
71static void tty_show_cursor (struct tty_display_info *); 71static void tty_show_cursor (struct tty_display_info *);
72static void tty_hide_cursor (struct tty_display_info *); 72static void tty_hide_cursor (struct tty_display_info *);
73static void tty_background_highlight (struct tty_display_info *tty); 73static void tty_background_highlight (struct tty_display_info *tty);
74static struct terminal *get_tty_terminal (Lisp_Object, int); 74static struct terminal *get_tty_terminal (Lisp_Object, bool);
75static void clear_tty_hooks (struct terminal *terminal); 75static void clear_tty_hooks (struct terminal *terminal);
76static void set_tty_hooks (struct terminal *terminal); 76static void set_tty_hooks (struct terminal *terminal);
77static void dissociate_if_controlling_tty (int fd); 77static void dissociate_if_controlling_tty (int fd);
78static void delete_tty (struct terminal *); 78static void delete_tty (struct terminal *);
79static _Noreturn void maybe_fatal (int must_succeed, struct terminal *terminal, 79static _Noreturn void maybe_fatal (bool, struct terminal *,
80 const char *str1, const char *str2, ...) 80 const char *, const char *, ...)
81 ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5); 81 ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5);
82static _Noreturn void vfatal (const char *str, va_list ap) 82static _Noreturn void vfatal (const char *str, va_list ap)
83 ATTRIBUTE_FORMAT_PRINTF (1, 0); 83 ATTRIBUTE_FORMAT_PRINTF (1, 0);
@@ -85,8 +85,7 @@ static _Noreturn void vfatal (const char *str, va_list ap)
85 85
86#define OUTPUT(tty, a) \ 86#define OUTPUT(tty, a) \
87 emacs_tputs ((tty), a, \ 87 emacs_tputs ((tty), a, \
88 (int) (FRAME_LINES (XFRAME (selected_frame)) \ 88 FRAME_LINES (XFRAME (selected_frame)) - curY (tty), \
89 - curY (tty)), \
90 cmputc) 89 cmputc)
91 90
92#define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc) 91#define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
@@ -695,7 +694,7 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
695{ 694{
696 unsigned char *conversion_buffer; 695 unsigned char *conversion_buffer;
697 struct coding_system *coding; 696 struct coding_system *coding;
698 size_t n, stringlen; 697 int n, stringlen;
699 698
700 struct tty_display_info *tty = FRAME_TTY (f); 699 struct tty_display_info *tty = FRAME_TTY (f);
701 700
@@ -1431,7 +1430,7 @@ static void append_glyph (struct it *);
1431static void append_composite_glyph (struct it *); 1430static void append_composite_glyph (struct it *);
1432static void produce_composite_glyph (struct it *); 1431static void produce_composite_glyph (struct it *);
1433static void append_glyphless_glyph (struct it *, int, const char *); 1432static void append_glyphless_glyph (struct it *, int, const char *);
1434static void produce_glyphless_glyph (struct it *, int, Lisp_Object); 1433static void produce_glyphless_glyph (struct it *, Lisp_Object);
1435 1434
1436/* Append glyphs to IT's glyph_row. Called from produce_glyphs for 1435/* Append glyphs to IT's glyph_row. Called from produce_glyphs for
1437 terminal frames if IT->glyph_row != NULL. IT->char_to_display is 1436 terminal frames if IT->glyph_row != NULL. IT->char_to_display is
@@ -1551,7 +1550,7 @@ produce_glyphs (struct it *it)
1551 1550
1552 if (it->what == IT_GLYPHLESS) 1551 if (it->what == IT_GLYPHLESS)
1553 { 1552 {
1554 produce_glyphless_glyph (it, 0, Qnil); 1553 produce_glyphless_glyph (it, Qnil);
1555 goto done; 1554 goto done;
1556 } 1555 }
1557 1556
@@ -1620,7 +1619,7 @@ produce_glyphs (struct it *it)
1620 Lisp_Object acronym = lookup_glyphless_char_display (-1, it); 1619 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
1621 1620
1622 eassert (it->what == IT_GLYPHLESS); 1621 eassert (it->what == IT_GLYPHLESS);
1623 produce_glyphless_glyph (it, 1, acronym); 1622 produce_glyphless_glyph (it, acronym);
1624 } 1623 }
1625 } 1624 }
1626 1625
@@ -1794,14 +1793,12 @@ append_glyphless_glyph (struct it *it, int face_id, const char *str)
1794 the character. See the description of enum 1793 the character. See the description of enum
1795 glyphless_display_method in dispextern.h for the details. 1794 glyphless_display_method in dispextern.h for the details.
1796 1795
1797 FOR_NO_FONT is nonzero if and only if this is for a character that 1796 ACRONYM, if non-nil, is an acronym string for the character.
1798 is not supported by the coding system of the terminal. ACRONYM, if
1799 non-nil, is an acronym string for the character.
1800 1797
1801 The glyphs actually produced are of type CHAR_GLYPH. */ 1798 The glyphs actually produced are of type CHAR_GLYPH. */
1802 1799
1803static void 1800static void
1804produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) 1801produce_glyphless_glyph (struct it *it, Lisp_Object acronym)
1805{ 1802{
1806 int face_id; 1803 int face_id;
1807 int len; 1804 int len;
@@ -1968,7 +1965,7 @@ turn_on_face (struct frame *f, int face_id)
1968 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground; 1965 ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
1969 if (fg >= 0 && ts) 1966 if (fg >= 0 && ts)
1970 { 1967 {
1971 p = tparam (ts, NULL, 0, (int) fg, 0, 0, 0); 1968 p = tparam (ts, NULL, 0, fg, 0, 0, 0);
1972 OUTPUT (tty, p); 1969 OUTPUT (tty, p);
1973 xfree (p); 1970 xfree (p);
1974 } 1971 }
@@ -1976,7 +1973,7 @@ turn_on_face (struct frame *f, int face_id)
1976 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background; 1973 ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
1977 if (bg >= 0 && ts) 1974 if (bg >= 0 && ts)
1978 { 1975 {
1979 p = tparam (ts, NULL, 0, (int) bg, 0, 0, 0); 1976 p = tparam (ts, NULL, 0, bg, 0, 0, 0);
1980 OUTPUT (tty, p); 1977 OUTPUT (tty, p);
1981 xfree (p); 1978 xfree (p);
1982 } 1979 }
@@ -2027,11 +2024,11 @@ turn_off_face (struct frame *f, int face_id)
2027} 2024}
2028 2025
2029 2026
2030/* Return non-zero if the terminal on frame F supports all of the 2027/* Return true if the terminal on frame F supports all of the
2031 capabilities in CAPS simultaneously, with foreground and background 2028 capabilities in CAPS simultaneously, with foreground and background
2032 colors FG and BG. */ 2029 colors FG and BG. */
2033 2030
2034int 2031bool
2035tty_capable_p (struct tty_display_info *tty, unsigned int caps, 2032tty_capable_p (struct tty_display_info *tty, unsigned int caps,
2036 unsigned long fg, unsigned long bg) 2033 unsigned long fg, unsigned long bg)
2037{ 2034{
@@ -2099,7 +2096,7 @@ static char *default_set_background;
2099/* Save or restore the default color-related capabilities of this 2096/* Save or restore the default color-related capabilities of this
2100 terminal. */ 2097 terminal. */
2101static void 2098static void
2102tty_default_color_capabilities (struct tty_display_info *tty, int save) 2099tty_default_color_capabilities (struct tty_display_info *tty, bool save)
2103{ 2100{
2104 2101
2105 if (save) 2102 if (save)
@@ -2209,7 +2206,7 @@ set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2209/* Return the tty display object specified by TERMINAL. */ 2206/* Return the tty display object specified by TERMINAL. */
2210 2207
2211static struct terminal * 2208static struct terminal *
2212get_tty_terminal (Lisp_Object terminal, int throw) 2209get_tty_terminal (Lisp_Object terminal, bool throw)
2213{ 2210{
2214 struct terminal *t = get_terminal (terminal, throw); 2211 struct terminal *t = get_terminal (terminal, throw);
2215 2212
@@ -2479,9 +2476,9 @@ term_mouse_moveto (int x, int y)
2479 const char *name; 2476 const char *name;
2480 int fd; 2477 int fd;
2481 name = (const char *) ttyname (0); 2478 name = (const char *) ttyname (0);
2482 fd = open (name, O_WRONLY); 2479 fd = emacs_open (name, O_WRONLY, 0);
2483 SOME_FUNCTION (x, y, fd); 2480 SOME_FUNCTION (x, y, fd);
2484 close (fd); 2481 emacs_close (fd);
2485 last_mouse_x = x; 2482 last_mouse_x = x;
2486 last_mouse_y = y; */ 2483 last_mouse_y = y; */
2487} 2484}
@@ -2519,7 +2516,7 @@ tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
2519 cursor_to (f, save_y, save_x); 2516 cursor_to (f, save_y, save_x);
2520} 2517}
2521 2518
2522static int 2519static bool
2523term_mouse_movement (FRAME_PTR frame, Gpm_Event *event) 2520term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2524{ 2521{
2525 /* Has the mouse moved off the glyph it was on at the last sighting? */ 2522 /* Has the mouse moved off the glyph it was on at the last sighting? */
@@ -2649,7 +2646,7 @@ handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct in
2649{ 2646{
2650 struct frame *f = XFRAME (tty->top_frame); 2647 struct frame *f = XFRAME (tty->top_frame);
2651 struct input_event ie; 2648 struct input_event ie;
2652 int do_help = 0; 2649 bool do_help = 0;
2653 int count = 0; 2650 int count = 0;
2654 2651
2655 EVENT_INIT (ie); 2652 EVENT_INIT (ie);
@@ -2934,7 +2931,7 @@ dissociate_if_controlling_tty (int fd)
2934 If MUST_SUCCEED is true, then all errors are fatal. */ 2931 If MUST_SUCCEED is true, then all errors are fatal. */
2935 2932
2936struct terminal * 2933struct terminal *
2937init_tty (const char *name, const char *terminal_type, int must_succeed) 2934init_tty (const char *name, const char *terminal_type, bool must_succeed)
2938{ 2935{
2939 char *area = NULL; 2936 char *area = NULL;
2940 char **address = &area; 2937 char **address = &area;
@@ -2942,7 +2939,7 @@ init_tty (const char *name, const char *terminal_type, int must_succeed)
2942 int status; 2939 int status;
2943 struct tty_display_info *tty = NULL; 2940 struct tty_display_info *tty = NULL;
2944 struct terminal *terminal = NULL; 2941 struct terminal *terminal = NULL;
2945 int ctty = 0; /* 1 if asked to open controlling tty. */ 2942 bool ctty = 0; /* True if asked to open controlling tty. */
2946 2943
2947 if (!terminal_type) 2944 if (!terminal_type)
2948 maybe_fatal (must_succeed, 0, 2945 maybe_fatal (must_succeed, 0,
@@ -3015,7 +3012,7 @@ init_tty (const char *name, const char *terminal_type, int must_succeed)
3015 name); 3012 name);
3016 if (!isatty (fd)) 3013 if (!isatty (fd))
3017 { 3014 {
3018 close (fd); 3015 emacs_close (fd);
3019 maybe_fatal (must_succeed, terminal, 3016 maybe_fatal (must_succeed, terminal,
3020 "Not a tty device: %s", 3017 "Not a tty device: %s",
3021 "Not a tty device: %s", 3018 "Not a tty device: %s",
@@ -3412,10 +3409,10 @@ vfatal (const char *str, va_list ap)
3412 3409
3413/* Auxiliary error-handling function for init_tty. 3410/* Auxiliary error-handling function for init_tty.
3414 Delete TERMINAL, then call error or fatal with str1 or str2, 3411 Delete TERMINAL, then call error or fatal with str1 or str2,
3415 respectively, according to whether MUST_SUCCEED is zero or not. */ 3412 respectively, according to whether MUST_SUCCEED is true. */
3416 3413
3417static void 3414static void
3418maybe_fatal (int must_succeed, struct terminal *terminal, 3415maybe_fatal (bool must_succeed, struct terminal *terminal,
3419 const char *str1, const char *str2, ...) 3416 const char *str1, const char *str2, ...)
3420{ 3417{
3421 va_list ap; 3418 va_list ap;
diff --git a/src/termcap.c b/src/termcap.c
index 99bbfce27f5..be05828eea6 100644
--- a/src/termcap.c
+++ b/src/termcap.c
@@ -213,8 +213,8 @@ tgetst1 (char *ptr, char **area)
213 abbreviation expansion makes that effort a little more hairy than 213 abbreviation expansion makes that effort a little more hairy than
214 its worth; this is cleaner. */ 214 its worth; this is cleaner. */
215 { 215 {
216 register int last_p_param = 0; 216 int last_p_param = 0;
217 int remove_p_params = 1; 217 bool remove_p_params = 1;
218 struct { char *beg; int len; } cut[11]; 218 struct { char *beg; int len; } cut[11];
219 219
220 for (cut[0].beg = p = ret; p < r - 3; p++) 220 for (cut[0].beg = p = ret; p < r - 3; p++)
@@ -318,26 +318,26 @@ struct termcap_buffer
318 char *beg; 318 char *beg;
319 ptrdiff_t size; 319 ptrdiff_t size;
320 char *ptr; 320 char *ptr;
321 int ateof; 321 bool ateof;
322 ptrdiff_t full; 322 ptrdiff_t full;
323 }; 323 };
324 324
325/* Forward declarations of static functions. */ 325/* Forward declarations of static functions. */
326 326
327static int scan_file (char *str, int fd, register struct termcap_buffer *bufp); 327static bool scan_file (char *, int, struct termcap_buffer *);
328static char *gobble_line (int fd, register struct termcap_buffer *bufp, char *append_end); 328static char *gobble_line (int, struct termcap_buffer *, char *);
329static int compare_contin (register char *str1, register char *str2); 329static bool compare_contin (char *, char *);
330static int name_match (char *line, char *name); 330static bool name_match (char *, char *);
331 331
332#ifdef MSDOS /* MW, May 1993 */ 332static bool
333static int
334valid_filename_p (char *fn) 333valid_filename_p (char *fn)
335{ 334{
335#ifdef MSDOS
336 return *fn == '/' || fn[1] == ':'; 336 return *fn == '/' || fn[1] == ':';
337}
338#else 337#else
339#define valid_filename_p(fn) (*(fn) == '/') 338 return *fn == '/';
340#endif 339#endif
340}
341 341
342/* Find the termcap entry data for terminal type NAME 342/* Find the termcap entry data for terminal type NAME
343 and store it in the block that BP points to. 343 and store it in the block that BP points to.
@@ -360,10 +360,10 @@ tgetent (char *bp, const char *name)
360 char *tc_search_point; 360 char *tc_search_point;
361 char *term; 361 char *term;
362 ptrdiff_t malloc_size = 0; 362 ptrdiff_t malloc_size = 0;
363 register int c; 363 int c;
364 char *tcenv = NULL; /* TERMCAP value, if it contains :tc=. */ 364 char *tcenv = NULL; /* TERMCAP value, if it contains :tc=. */
365 char *indirect = NULL; /* Terminal type in :tc= in TERMCAP value. */ 365 char *indirect = NULL; /* Terminal type in :tc= in TERMCAP value. */
366 int filep; 366 bool filep;
367 367
368#ifdef INTERNAL_TERMINAL 368#ifdef INTERNAL_TERMINAL
369 /* For the internal terminal we don't want to read any termcap file, 369 /* For the internal terminal we don't want to read any termcap file,
@@ -427,11 +427,7 @@ tgetent (char *bp, const char *name)
427 427
428 /* Here we know we must search a file and termcap_name has its name. */ 428 /* Here we know we must search a file and termcap_name has its name. */
429 429
430#ifdef MSDOS 430 fd = emacs_open (termcap_name, O_RDONLY | O_TEXT, 0);
431 fd = open (termcap_name, O_RDONLY|O_TEXT, 0);
432#else
433 fd = open (termcap_name, O_RDONLY, 0);
434#endif
435 if (fd < 0) 431 if (fd < 0)
436 return -1; 432 return -1;
437 433
@@ -459,7 +455,7 @@ tgetent (char *bp, const char *name)
459 /* Scan the file, reading it via buf, till find start of main entry. */ 455 /* Scan the file, reading it via buf, till find start of main entry. */
460 if (scan_file (term, fd, &buf) == 0) 456 if (scan_file (term, fd, &buf) == 0)
461 { 457 {
462 close (fd); 458 emacs_close (fd);
463 xfree (buf.beg); 459 xfree (buf.beg);
464 if (malloc_size) 460 if (malloc_size)
465 xfree (bp); 461 xfree (bp);
@@ -497,7 +493,7 @@ tgetent (char *bp, const char *name)
497 term = tgetst1 (tc_search_point, (char **) 0); 493 term = tgetst1 (tc_search_point, (char **) 0);
498 } 494 }
499 495
500 close (fd); 496 emacs_close (fd);
501 xfree (buf.beg); 497 xfree (buf.beg);
502 498
503 if (malloc_size) 499 if (malloc_size)
@@ -514,10 +510,10 @@ tgetent (char *bp, const char *name)
514 Return 1 if successful, with that line in BUFP, 510 Return 1 if successful, with that line in BUFP,
515 or 0 if no entry is found in the file. */ 511 or 0 if no entry is found in the file. */
516 512
517static int 513static bool
518scan_file (char *str, int fd, register struct termcap_buffer *bufp) 514scan_file (char *str, int fd, struct termcap_buffer *bufp)
519{ 515{
520 register char *end; 516 char *end;
521 517
522 bufp->ptr = bufp->beg; 518 bufp->ptr = bufp->beg;
523 bufp->full = 0; 519 bufp->full = 0;
@@ -548,13 +544,13 @@ scan_file (char *str, int fd, register struct termcap_buffer *bufp)
548 return 0; 544 return 0;
549} 545}
550 546
551/* Return nonzero if NAME is one of the names specified 547/* Return true if NAME is one of the names specified
552 by termcap entry LINE. */ 548 by termcap entry LINE. */
553 549
554static int 550static bool
555name_match (char *line, char *name) 551name_match (char *line, char *name)
556{ 552{
557 register char *tem; 553 char *tem;
558 554
559 if (!compare_contin (line, name)) 555 if (!compare_contin (line, name))
560 return 1; 556 return 1;
@@ -566,18 +562,18 @@ name_match (char *line, char *name)
566 return 0; 562 return 0;
567} 563}
568 564
569static int 565static bool
570compare_contin (register char *str1, register char *str2) 566compare_contin (char *str1, char *str2)
571{ 567{
572 register int c1, c2;
573 while (1) 568 while (1)
574 { 569 {
575 c1 = *str1++; 570 int c1 = *str1++;
576 c2 = *str2++; 571 int c2 = *str2++;
577 while (c1 == '\\' && *str1 == '\n') 572 while (c1 == '\\' && *str1 == '\n')
578 { 573 {
579 str1++; 574 str1++;
580 while ((c1 = *str1++) == ' ' || c1 == '\t'); 575 while ((c1 = *str1++) == ' ' || c1 == '\t')
576 continue;
581 } 577 }
582 if (c2 == '\0') 578 if (c2 == '\0')
583 { 579 {
@@ -651,57 +647,3 @@ gobble_line (int fd, register struct termcap_buffer *bufp, char *append_end)
651 } 647 }
652 return end + 1; 648 return end + 1;
653} 649}
654
655#ifdef TEST
656
657#include <stdio.h>
658
659static void
660tprint (char *cap)
661{
662 char *x = tgetstr (cap, 0);
663 register char *y;
664
665 printf ("%s: ", cap);
666 if (x)
667 {
668 for (y = x; *y; y++)
669 if (*y <= ' ' || *y == 0177)
670 printf ("\\%0o", *y);
671 else
672 putchar (*y);
673 free (x);
674 }
675 else
676 printf ("none");
677 putchar ('\n');
678}
679
680int
681main (int argc, char **argv)
682{
683 char *term;
684 char *buf;
685
686 term = argv[1];
687 printf ("TERM: %s\n", term);
688
689 buf = (char *) tgetent (0, term);
690 if ((int) buf <= 0)
691 {
692 printf ("No entry.\n");
693 return 0;
694 }
695
696 printf ("Entry: %s\n", buf);
697
698 tprint ("cm");
699 tprint ("AL");
700
701 printf ("co: %d\n", tgetnum ("co"));
702 printf ("am: %d\n", tgetflag ("am"));
703
704 return 0;
705}
706
707#endif /* TEST */
diff --git a/src/termhooks.h b/src/termhooks.h
index fdbeda076b7..f11f5ae9ffc 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -646,7 +646,7 @@ extern struct terminal *terminal_list;
646 (((d)->type != output_termcap && (d)->type != output_msdos_raw) \ 646 (((d)->type != output_termcap && (d)->type != output_msdos_raw) \
647 || (d)->display_info.tty->input) 647 || (d)->display_info.tty->input)
648 648
649extern struct terminal *get_terminal (Lisp_Object terminal, int); 649extern struct terminal *get_terminal (Lisp_Object terminal, bool);
650extern struct terminal *create_terminal (void); 650extern struct terminal *create_terminal (void);
651extern void delete_terminal (struct terminal *); 651extern void delete_terminal (struct terminal *);
652 652
diff --git a/src/terminal.c b/src/terminal.c
index c99c39c64ae..c55fd4eb077 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -199,11 +199,11 @@ ins_del_lines (struct frame *f, int vpos, int n)
199 199
200/* Return the terminal object specified by TERMINAL. TERMINAL may be 200/* Return the terminal object specified by TERMINAL. TERMINAL may be
201 a terminal object, a frame, or nil for the terminal device of the 201 a terminal object, a frame, or nil for the terminal device of the
202 current frame. If THROW is zero, return NULL for failure, 202 current frame. If THROW is false, return NULL for failure,
203 otherwise throw an error. */ 203 otherwise throw an error. */
204 204
205struct terminal * 205struct terminal *
206get_terminal (Lisp_Object terminal, int throw) 206get_terminal (Lisp_Object terminal, bool throw)
207{ 207{
208 struct terminal *result = NULL; 208 struct terminal *result = NULL;
209 209
diff --git a/src/undo.c b/src/undo.c
index d8711882fbf..234b8510f0a 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -229,10 +229,9 @@ record_first_change (void)
229 if (base_buffer->base_buffer) 229 if (base_buffer->base_buffer)
230 base_buffer = base_buffer->base_buffer; 230 base_buffer = base_buffer->base_buffer;
231 231
232 bset_undo_list 232 bset_undo_list (current_buffer,
233 (current_buffer, 233 Fcons (Fcons (Qt, Fvisited_file_modtime ()),
234 Fcons (Fcons (Qt, make_lisp_time (base_buffer->modtime)), 234 BVAR (current_buffer, undo_list)));
235 BVAR (current_buffer, undo_list)));
236} 235}
237 236
238/* Record a change in property PROP (whose old value was VAL) 237/* Record a change in property PROP (whose old value was VAL)
diff --git a/src/unexaix.c b/src/unexaix.c
index 44a824b8c12..757ba6f51b3 100644
--- a/src/unexaix.c
+++ b/src/unexaix.c
@@ -42,6 +42,7 @@ what you give them. Help stamp out software-hoarding! */
42 42
43#include <config.h> 43#include <config.h>
44#include "unexec.h" 44#include "unexec.h"
45#include "lisp.h"
45 46
46#define PERROR(file) report_error (file, new) 47#define PERROR(file) report_error (file, new)
47#include <a.out.h> 48#include <a.out.h>
@@ -93,13 +94,10 @@ static int pagemask;
93static _Noreturn void 94static _Noreturn void
94report_error (const char *file, int fd) 95report_error (const char *file, int fd)
95{ 96{
97 int err = errno;
96 if (fd) 98 if (fd)
97 { 99 emacs_close (fd);
98 int failed_errno = errno; 100 report_file_errno ("Cannot unexec", Fcons (build_string (file), Qnil), err);
99 close (fd);
100 errno = failed_errno;
101 }
102 report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil));
103} 101}
104 102
105#define ERROR0(msg) report_error_1 (new, msg) 103#define ERROR0(msg) report_error_1 (new, msg)
@@ -110,7 +108,7 @@ static _Noreturn void ATTRIBUTE_FORMAT_PRINTF (2, 3)
110report_error_1 (int fd, const char *msg, ...) 108report_error_1 (int fd, const char *msg, ...)
111{ 109{
112 va_list ap; 110 va_list ap;
113 close (fd); 111 emacs_close (fd);
114 va_start (ap, msg); 112 va_start (ap, msg);
115 verror (msg, ap); 113 verror (msg, ap);
116 va_end (ap); 114 va_end (ap);
@@ -132,11 +130,11 @@ unexec (const char *new_name, const char *a_name)
132{ 130{
133 int new = -1, a_out = -1; 131 int new = -1, a_out = -1;
134 132
135 if (a_name && (a_out = open (a_name, O_RDONLY)) < 0) 133 if (a_name && (a_out = emacs_open (a_name, O_RDONLY, 0)) < 0)
136 { 134 {
137 PERROR (a_name); 135 PERROR (a_name);
138 } 136 }
139 if ((new = creat (new_name, 0666)) < 0) 137 if ((new = emacs_open (new_name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
140 { 138 {
141 PERROR (new_name); 139 PERROR (new_name);
142 } 140 }
@@ -147,13 +145,13 @@ unexec (const char *new_name, const char *a_name)
147 || adjust_lnnoptrs (new, a_out, new_name) < 0 145 || adjust_lnnoptrs (new, a_out, new_name) < 0
148 || unrelocate_symbols (new, a_out, a_name, new_name) < 0) 146 || unrelocate_symbols (new, a_out, a_name, new_name) < 0)
149 { 147 {
150 close (new); 148 emacs_close (new);
151 return; 149 return;
152 } 150 }
153 151
154 close (new); 152 emacs_close (new);
155 if (a_out >= 0) 153 if (a_out >= 0)
156 close (a_out); 154 emacs_close (a_out);
157 mark_x (new_name); 155 mark_x (new_name);
158} 156}
159 157
@@ -503,7 +501,7 @@ adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name)
503 if (!lnnoptr || !f_hdr.f_symptr) 501 if (!lnnoptr || !f_hdr.f_symptr)
504 return 0; 502 return 0;
505 503
506 if ((new = open (new_name, O_RDWR)) < 0) 504 if ((new = emacs_open (new_name, O_RDWR, 0)) < 0)
507 { 505 {
508 PERROR (new_name); 506 PERROR (new_name);
509 return -1; 507 return -1;
@@ -533,7 +531,7 @@ adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name)
533 } 531 }
534 } 532 }
535 } 533 }
536 close (new); 534 emacs_close (new);
537 535
538 return 0; 536 return 0;
539} 537}
diff --git a/src/unexcoff.c b/src/unexcoff.c
index 2e662a34145..c467e59a665 100644
--- a/src/unexcoff.c
+++ b/src/unexcoff.c
@@ -52,6 +52,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
52 52
53#include <config.h> 53#include <config.h>
54#include "unexec.h" 54#include "unexec.h"
55#include "lisp.h"
55 56
56#define PERROR(file) report_error (file, new) 57#define PERROR(file) report_error (file, new)
57 58
@@ -126,9 +127,10 @@ static int pagemask;
126static void 127static void
127report_error (const char *file, int fd) 128report_error (const char *file, int fd)
128{ 129{
130 int err = errno;
129 if (fd) 131 if (fd)
130 close (fd); 132 emacs_close (fd);
131 report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil)); 133 report_file_errno ("Cannot unexec", Fcons (build_string (file), Qnil), err);
132} 134}
133 135
134#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1 136#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
@@ -138,7 +140,7 @@ report_error (const char *file, int fd)
138static void 140static void
139report_error_1 (int fd, const char *msg, int a1, int a2) 141report_error_1 (int fd, const char *msg, int a1, int a2)
140{ 142{
141 close (fd); 143 emacs_close (fd);
142 error (msg, a1, a2); 144 error (msg, a1, a2);
143} 145}
144 146
@@ -486,7 +488,7 @@ adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name)
486#ifdef MSDOS 488#ifdef MSDOS
487 if ((new = writedesc) < 0) 489 if ((new = writedesc) < 0)
488#else 490#else
489 if ((new = open (new_name, O_RDWR)) < 0) 491 if ((new = emacs_open (new_name, O_RDWR, 0)) < 0)
490#endif 492#endif
491 { 493 {
492 PERROR (new_name); 494 PERROR (new_name);
@@ -510,7 +512,7 @@ adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name)
510 } 512 }
511 } 513 }
512#ifndef MSDOS 514#ifndef MSDOS
513 close (new); 515 emacs_close (new);
514#endif 516#endif
515 return 0; 517 return 0;
516} 518}
@@ -525,11 +527,11 @@ unexec (const char *new_name, const char *a_name)
525{ 527{
526 int new = -1, a_out = -1; 528 int new = -1, a_out = -1;
527 529
528 if (a_name && (a_out = open (a_name, O_RDONLY)) < 0) 530 if (a_name && (a_out = emacs_open (a_name, O_RDONLY, 0)) < 0)
529 { 531 {
530 PERROR (a_name); 532 PERROR (a_name);
531 } 533 }
532 if ((new = creat (new_name, 0666)) < 0) 534 if ((new = emacs_open (new_name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
533 { 535 {
534 PERROR (new_name); 536 PERROR (new_name);
535 } 537 }
@@ -540,13 +542,13 @@ unexec (const char *new_name, const char *a_name)
540 || adjust_lnnoptrs (new, a_out, new_name) < 0 542 || adjust_lnnoptrs (new, a_out, new_name) < 0
541 ) 543 )
542 { 544 {
543 close (new); 545 emacs_close (new);
544 return; 546 return;
545 } 547 }
546 548
547 close (new); 549 emacs_close (new);
548 if (a_out >= 0) 550 if (a_out >= 0)
549 close (a_out); 551 emacs_close (a_out);
550 mark_x (new_name); 552 mark_x (new_name);
551} 553}
552 554
diff --git a/src/unexcw.c b/src/unexcw.c
index 1290c28d245..12435a85051 100644
--- a/src/unexcw.c
+++ b/src/unexcw.c
@@ -20,8 +20,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 20
21#include <config.h> 21#include <config.h>
22#include "unexec.h" 22#include "unexec.h"
23#include "lisp.h"
23 24
24#include <lisp.h>
25#include <stdio.h> 25#include <stdio.h>
26#include <fcntl.h> 26#include <fcntl.h>
27#include <a.out.h> 27#include <a.out.h>
@@ -298,9 +298,9 @@ unexec (const char *outfile, const char *infile)
298 infile = add_exe_suffix_if_necessary (infile, infile_buffer); 298 infile = add_exe_suffix_if_necessary (infile, infile_buffer);
299 outfile = add_exe_suffix_if_necessary (outfile, outfile_buffer); 299 outfile = add_exe_suffix_if_necessary (outfile, outfile_buffer);
300 300
301 fd_in = open (infile, O_RDONLY | O_BINARY); 301 fd_in = emacs_open (infile, O_RDONLY | O_BINARY, 0);
302 assert (fd_in >= 0); 302 assert (fd_in >= 0);
303 fd_out = open (outfile, O_RDWR | O_TRUNC | O_CREAT | O_BINARY, 0755); 303 fd_out = emacs_open (outfile, O_RDWR | O_TRUNC | O_CREAT | O_BINARY, 0755);
304 assert (fd_out >= 0); 304 assert (fd_out >= 0);
305 for (;;) 305 for (;;)
306 { 306 {
@@ -316,13 +316,13 @@ unexec (const char *outfile, const char *infile)
316 ret2 = write (fd_out, buffer, ret); 316 ret2 = write (fd_out, buffer, ret);
317 assert (ret2 == ret); 317 assert (ret2 == ret);
318 } 318 }
319 ret = close (fd_in); 319 ret = emacs_close (fd_in);
320 assert (ret == 0); 320 assert (ret == 0);
321 321
322 bss_sbrk_did_unexec = 1; 322 bss_sbrk_did_unexec = 1;
323 fixup_executable (fd_out); 323 fixup_executable (fd_out);
324 bss_sbrk_did_unexec = 0; 324 bss_sbrk_did_unexec = 0;
325 325
326 ret = close (fd_out); 326 ret = emacs_close (fd_out);
327 assert (ret == 0); 327 assert (ret == 0);
328} 328}
diff --git a/src/unexelf.c b/src/unexelf.c
index 4e50bb86367..e2412393286 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -386,9 +386,8 @@ temacs:
386 Instead we read the whole file, modify it, and write it out. */ 386 Instead we read the whole file, modify it, and write it out. */
387 387
388#include <config.h> 388#include <config.h>
389#include <unexec.h> 389#include "unexec.h"
390 390#include "lisp.h"
391extern _Noreturn void fatal (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
392 391
393#include <errno.h> 392#include <errno.h>
394#include <fcntl.h> 393#include <fcntl.h>
@@ -672,7 +671,7 @@ unexec (const char *new_name, const char *old_name)
672 /* Open the old file, allocate a buffer of the right size, and read 671 /* Open the old file, allocate a buffer of the right size, and read
673 in the file contents. */ 672 in the file contents. */
674 673
675 old_file = open (old_name, O_RDONLY); 674 old_file = emacs_open (old_name, O_RDONLY, 0);
676 675
677 if (old_file < 0) 676 if (old_file < 0)
678 fatal ("Can't open %s for reading: %s", old_name, strerror (errno)); 677 fatal ("Can't open %s for reading: %s", old_name, strerror (errno));
@@ -681,7 +680,7 @@ unexec (const char *new_name, const char *old_name)
681 fatal ("Can't fstat (%s): %s", old_name, strerror (errno)); 680 fatal ("Can't fstat (%s): %s", old_name, strerror (errno));
682 681
683#if MAP_ANON == 0 682#if MAP_ANON == 0
684 mmap_fd = open ("/dev/zero", O_RDONLY); 683 mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0);
685 if (mmap_fd < 0) 684 if (mmap_fd < 0)
686 fatal ("Can't open /dev/zero for reading: %s", strerror (errno)); 685 fatal ("Can't open /dev/zero for reading: %s", strerror (errno));
687#endif 686#endif
@@ -801,7 +800,7 @@ unexec (const char *new_name, const char *old_name)
801 the image of the new file. Set pointers to various interesting 800 the image of the new file. Set pointers to various interesting
802 objects. */ 801 objects. */
803 802
804 new_file = open (new_name, O_RDWR | O_CREAT, 0666); 803 new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0666);
805 if (new_file < 0) 804 if (new_file < 0)
806 fatal ("Can't creat (%s): %s", new_name, strerror (errno)); 805 fatal ("Can't creat (%s): %s", new_name, strerror (errno));
807 806
@@ -1313,13 +1312,13 @@ temacs:
1313 /* Close the files and make the new file executable. */ 1312 /* Close the files and make the new file executable. */
1314 1313
1315#if MAP_ANON == 0 1314#if MAP_ANON == 0
1316 close (mmap_fd); 1315 emacs_close (mmap_fd);
1317#endif 1316#endif
1318 1317
1319 if (close (old_file) != 0) 1318 if (emacs_close (old_file) != 0)
1320 fatal ("Can't close (%s): %s", old_name, strerror (errno)); 1319 fatal ("Can't close (%s): %s", old_name, strerror (errno));
1321 1320
1322 if (close (new_file) != 0) 1321 if (emacs_close (new_file) != 0)
1323 fatal ("Can't close (%s): %s", new_name, strerror (errno)); 1322 fatal ("Can't close (%s): %s", new_name, strerror (errno));
1324 1323
1325 if (stat (new_name, &stat_buf) != 0) 1324 if (stat (new_name, &stat_buf) != 0)
diff --git a/src/unexhp9k800.c b/src/unexhp9k800.c
index ce65faffd4e..bee2517307a 100644
--- a/src/unexhp9k800.c
+++ b/src/unexhp9k800.c
@@ -51,6 +51,7 @@
51 51
52#include <config.h> 52#include <config.h>
53#include "unexec.h" 53#include "unexec.h"
54#include "lisp.h"
54 55
55#include <stdio.h> 56#include <stdio.h>
56#include <fcntl.h> 57#include <fcntl.h>
@@ -268,10 +269,10 @@ unexec (const char *new_name, /* name of the new a.out file to be created *
268 intact. NOT implemented. */ 269 intact. NOT implemented. */
269 270
270 /* Open the input and output a.out files */ 271 /* Open the input and output a.out files */
271 old = open (old_name, O_RDONLY); 272 old = emacs_open (old_name, O_RDONLY, 0);
272 if (old < 0) 273 if (old < 0)
273 { perror (old_name); exit (1); } 274 { perror (old_name); exit (1); }
274 new = open (new_name, O_CREAT|O_RDWR|O_TRUNC, 0777); 275 new = emacs_open (new_name, O_CREAT | O_RDWR | O_TRUNC, 0777);
275 if (new < 0) 276 if (new < 0)
276 { perror (new_name); exit (1); } 277 { perror (new_name); exit (1); }
277 278
@@ -305,6 +306,6 @@ unexec (const char *new_name, /* name of the new a.out file to be created *
305 write_header (new, &hdr, &auxhdr); 306 write_header (new, &hdr, &auxhdr);
306 307
307 /* Close the binary file */ 308 /* Close the binary file */
308 close (old); 309 emacs_close (old);
309 close (new); 310 emacs_close (new);
310} 311}
diff --git a/src/unexmacosx.c b/src/unexmacosx.c
index 8d4e636fa5c..87848b012ba 100644
--- a/src/unexmacosx.c
+++ b/src/unexmacosx.c
@@ -97,6 +97,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
97#undef free 97#undef free
98 98
99#include "unexec.h" 99#include "unexec.h"
100#include "lisp.h"
100 101
101#include <stdio.h> 102#include <stdio.h>
102#include <fcntl.h> 103#include <fcntl.h>
@@ -1322,16 +1323,16 @@ unexec (const char *outfile, const char *infile)
1322 unexec_error ("Unexec from a dumped executable is not supported."); 1323 unexec_error ("Unexec from a dumped executable is not supported.");
1323 1324
1324 pagesize = getpagesize (); 1325 pagesize = getpagesize ();
1325 infd = open (infile, O_RDONLY, 0); 1326 infd = emacs_open (infile, O_RDONLY, 0);
1326 if (infd < 0) 1327 if (infd < 0)
1327 { 1328 {
1328 unexec_error ("cannot open input file `%s'", infile); 1329 unexec_error ("cannot open input file `%s'", infile);
1329 } 1330 }
1330 1331
1331 outfd = open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0755); 1332 outfd = emacs_open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0755);
1332 if (outfd < 0) 1333 if (outfd < 0)
1333 { 1334 {
1334 close (infd); 1335 emacs_close (infd);
1335 unexec_error ("cannot open output file `%s'", outfile); 1336 unexec_error ("cannot open output file `%s'", outfile);
1336 } 1337 }
1337 1338
@@ -1345,7 +1346,7 @@ unexec (const char *outfile, const char *infile)
1345 1346
1346 dump_it (); 1347 dump_it ();
1347 1348
1348 close (outfd); 1349 emacs_close (outfd);
1349} 1350}
1350 1351
1351 1352
diff --git a/src/w32.c b/src/w32.c
index 230479cd61a..1a3d81bbffc 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -234,6 +234,8 @@ extern int sys_access (const char *, int);
234extern void *e_malloc (size_t); 234extern void *e_malloc (size_t);
235extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, 235extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
236 EMACS_TIME *, void *); 236 EMACS_TIME *, void *);
237extern int sys_dup (int);
238
237 239
238 240
239 241
@@ -6719,10 +6721,16 @@ sys_sendto (int s, const char * buf, int len, int flags,
6719} 6721}
6720 6722
6721/* Windows does not have an fcntl function. Provide an implementation 6723/* Windows does not have an fcntl function. Provide an implementation
6722 solely for making sockets non-blocking. */ 6724 good enough for Emacs. */
6723int 6725int
6724fcntl (int s, int cmd, int options) 6726fcntl (int s, int cmd, int options)
6725{ 6727{
6728 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
6729 invoked in a context where fd1 is closed and all descriptors less
6730 than fd1 are open, so sys_dup is an adequate implementation. */
6731 if (cmd == F_DUPFD_CLOEXEC)
6732 return sys_dup (s);
6733
6726 if (winsock_lib == NULL) 6734 if (winsock_lib == NULL)
6727 { 6735 {
6728 errno = ENETDOWN; 6736 errno = ENETDOWN;
@@ -6864,13 +6872,14 @@ sys_dup2 (int src, int dst)
6864 return rc; 6872 return rc;
6865} 6873}
6866 6874
6867/* Unix pipe() has only one arg */
6868int 6875int
6869sys_pipe (int * phandles) 6876pipe2 (int * phandles, int pipe2_flags)
6870{ 6877{
6871 int rc; 6878 int rc;
6872 unsigned flags; 6879 unsigned flags;
6873 6880
6881 eassert (pipe2_flags == O_CLOEXEC);
6882
6874 /* make pipe handles non-inheritable; when we spawn a child, we 6883 /* make pipe handles non-inheritable; when we spawn a child, we
6875 replace the relevant handle with an inheritable one. Also put 6884 replace the relevant handle with an inheritable one. Also put
6876 pipes into binary mode; we will do text mode translation ourselves 6885 pipes into binary mode; we will do text mode translation ourselves
diff --git a/src/w32.h b/src/w32.h
index 17da0778db1..9c1f1efa699 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -188,7 +188,7 @@ extern int random (void);
188 188
189extern int fchmod (int, mode_t); 189extern int fchmod (int, mode_t);
190extern int sys_rename_replace (char const *, char const *, BOOL); 190extern int sys_rename_replace (char const *, char const *, BOOL);
191extern int sys_pipe (int *); 191extern int pipe2 (int *, int);
192 192
193extern void set_process_dir (char *); 193extern void set_process_dir (char *);
194extern int sys_spawnve (int, char *, char **, char **); 194extern int sys_spawnve (int, char *, char **, char **);
diff --git a/src/w32fns.c b/src/w32fns.c
index 46fb02d96a1..3fa23c166e2 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -106,6 +106,7 @@ Lisp_Object Qalt;
106Lisp_Object Qctrl; 106Lisp_Object Qctrl;
107Lisp_Object Qcontrol; 107Lisp_Object Qcontrol;
108Lisp_Object Qshift; 108Lisp_Object Qshift;
109static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes;
109 110
110 111
111/* Prefix for system colors. */ 112/* Prefix for system colors. */
@@ -131,6 +132,15 @@ static HWND track_mouse_window;
131#ifndef MONITOR_DEFAULT_TO_NEAREST 132#ifndef MONITOR_DEFAULT_TO_NEAREST
132#define MONITOR_DEFAULT_TO_NEAREST 2 133#define MONITOR_DEFAULT_TO_NEAREST 2
133#endif 134#endif
135#ifndef MONITORINFOF_PRIMARY
136#define MONITORINFOF_PRIMARY 1
137#endif
138#ifndef SM_XVIRTUALSCREEN
139#define SM_XVIRTUALSCREEN 76
140#endif
141#ifndef SM_YVIRTUALSCREEN
142#define SM_YVIRTUALSCREEN 77
143#endif
134/* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't. 144/* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't.
135 To avoid a compile error on one or the other, redefine with a new name. */ 145 To avoid a compile error on one or the other, redefine with a new name. */
136struct MONITOR_INFO 146struct MONITOR_INFO
@@ -141,6 +151,18 @@ struct MONITOR_INFO
141 DWORD dwFlags; 151 DWORD dwFlags;
142}; 152};
143 153
154#ifndef CCHDEVICENAME
155#define CCHDEVICENAME 32
156#endif
157struct MONITOR_INFO_EX
158{
159 DWORD cbSize;
160 RECT rcMonitor;
161 RECT rcWork;
162 DWORD dwFlags;
163 char szDevice[CCHDEVICENAME];
164};
165
144/* Reportedly, MSVC does not have this in its headers. */ 166/* Reportedly, MSVC does not have this in its headers. */
145#if defined (_MSC_VER) && _WIN32_WINNT < 0x0500 167#if defined (_MSC_VER) && _WIN32_WINNT < 0x0500
146DECLARE_HANDLE(HMONITOR); 168DECLARE_HANDLE(HMONITOR);
@@ -159,6 +181,10 @@ typedef BOOL (WINAPI * GetMonitorInfo_Proc)
159 (IN HMONITOR monitor, OUT struct MONITOR_INFO* info); 181 (IN HMONITOR monitor, OUT struct MONITOR_INFO* info);
160typedef HMONITOR (WINAPI * MonitorFromWindow_Proc) 182typedef HMONITOR (WINAPI * MonitorFromWindow_Proc)
161 (IN HWND hwnd, IN DWORD dwFlags); 183 (IN HWND hwnd, IN DWORD dwFlags);
184typedef BOOL CALLBACK (* MonitorEnum_Proc)
185 (IN HMONITOR monitor, IN HDC hdc, IN RECT *rcMonitor, IN LPARAM dwData);
186typedef BOOL (WINAPI * EnumDisplayMonitors_Proc)
187 (IN HDC hdc, IN RECT *rcClip, IN MonitorEnum_Proc fnEnum, IN LPARAM dwData);
162 188
163TrackMouseEvent_Proc track_mouse_event_fn = NULL; 189TrackMouseEvent_Proc track_mouse_event_fn = NULL;
164ImmGetCompositionString_Proc get_composition_string_fn = NULL; 190ImmGetCompositionString_Proc get_composition_string_fn = NULL;
@@ -168,6 +194,7 @@ ImmSetCompositionWindow_Proc set_ime_composition_window_fn = NULL;
168MonitorFromPoint_Proc monitor_from_point_fn = NULL; 194MonitorFromPoint_Proc monitor_from_point_fn = NULL;
169GetMonitorInfo_Proc get_monitor_info_fn = NULL; 195GetMonitorInfo_Proc get_monitor_info_fn = NULL;
170MonitorFromWindow_Proc monitor_from_window_fn = NULL; 196MonitorFromWindow_Proc monitor_from_window_fn = NULL;
197EnumDisplayMonitors_Proc enum_display_monitors_fn = NULL;
171 198
172#ifdef NTGUI_UNICODE 199#ifdef NTGUI_UNICODE
173#define unicode_append_menu AppendMenuW 200#define unicode_append_menu AppendMenuW
@@ -4674,7 +4701,11 @@ DEFUN ("x-display-pixel-width", Fx_display_pixel_width,
4674 doc: /* Return the width in pixels of DISPLAY. 4701 doc: /* Return the width in pixels of DISPLAY.
4675The optional argument DISPLAY specifies which display to ask about. 4702The optional argument DISPLAY specifies which display to ask about.
4676DISPLAY should be either a frame or a display name (a string). 4703DISPLAY should be either a frame or a display name (a string).
4677If omitted or nil, that stands for the selected frame's display. */) 4704If omitted or nil, that stands for the selected frame's display.
4705
4706On \"multi-monitor\" setups this refers to the pixel width for all
4707physical monitors associated with DISPLAY. To get information for
4708each physical monitor, use `display-monitor-attributes-list'. */)
4678 (Lisp_Object display) 4709 (Lisp_Object display)
4679{ 4710{
4680 struct w32_display_info *dpyinfo = check_x_display_info (display); 4711 struct w32_display_info *dpyinfo = check_x_display_info (display);
@@ -4687,7 +4718,11 @@ DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
4687 doc: /* Return the height in pixels of DISPLAY. 4718 doc: /* Return the height in pixels of DISPLAY.
4688The optional argument DISPLAY specifies which display to ask about. 4719The optional argument DISPLAY specifies which display to ask about.
4689DISPLAY should be either a frame or a display name (a string). 4720DISPLAY should be either a frame or a display name (a string).
4690If omitted or nil, that stands for the selected frame's display. */) 4721If omitted or nil, that stands for the selected frame's display.
4722
4723On \"multi-monitor\" setups this refers to the pixel height for all
4724physical monitors associated with DISPLAY. To get information for
4725each physical monitor, use `display-monitor-attributes-list'. */)
4691 (Lisp_Object display) 4726 (Lisp_Object display)
4692{ 4727{
4693 struct w32_display_info *dpyinfo = check_x_display_info (display); 4728 struct w32_display_info *dpyinfo = check_x_display_info (display);
@@ -4779,41 +4814,46 @@ DEFUN ("x-display-mm-height", Fx_display_mm_height,
4779 doc: /* Return the height in millimeters of DISPLAY. 4814 doc: /* Return the height in millimeters of DISPLAY.
4780The optional argument DISPLAY specifies which display to ask about. 4815The optional argument DISPLAY specifies which display to ask about.
4781DISPLAY should be either a frame or a display name (a string). 4816DISPLAY should be either a frame or a display name (a string).
4782If omitted or nil, that stands for the selected frame's display. */) 4817If omitted or nil, that stands for the selected frame's display.
4818
4819On \"multi-monitor\" setups this refers to the height in millimeters for
4820all physical monitors associated with DISPLAY. To get information
4821for each physical monitor, use `display-monitor-attributes-list'. */)
4783 (Lisp_Object display) 4822 (Lisp_Object display)
4784{ 4823{
4785 struct w32_display_info *dpyinfo = check_x_display_info (display); 4824 struct w32_display_info *dpyinfo = check_x_display_info (display);
4786 HDC hdc; 4825 HDC hdc;
4787 int cap; 4826 double mm_per_pixel;
4788
4789 hdc = GetDC (dpyinfo->root_window);
4790 4827
4791 cap = GetDeviceCaps (hdc, VERTSIZE); 4828 hdc = GetDC (NULL);
4829 mm_per_pixel = ((double) GetDeviceCaps (hdc, VERTSIZE)
4830 / GetDeviceCaps (hdc, VERTRES));
4831 ReleaseDC (NULL, hdc);
4792 4832
4793 ReleaseDC (dpyinfo->root_window, hdc); 4833 return make_number (x_display_pixel_height (dpyinfo) * mm_per_pixel + 0.5);
4794
4795 return make_number (cap);
4796} 4834}
4797 4835
4798DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0, 4836DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
4799 doc: /* Return the width in millimeters of DISPLAY. 4837 doc: /* Return the width in millimeters of DISPLAY.
4800The optional argument DISPLAY specifies which display to ask about. 4838The optional argument DISPLAY specifies which display to ask about.
4801DISPLAY should be either a frame or a display name (a string). 4839DISPLAY should be either a frame or a display name (a string).
4802If omitted or nil, that stands for the selected frame's display. */) 4840If omitted or nil, that stands for the selected frame's display.
4841
4842On \"multi-monitor\" setups this refers to the width in millimeters for
4843all physical monitors associated with TERMINAL. To get information
4844for each physical monitor, use `display-monitor-attributes-list'. */)
4803 (Lisp_Object display) 4845 (Lisp_Object display)
4804{ 4846{
4805 struct w32_display_info *dpyinfo = check_x_display_info (display); 4847 struct w32_display_info *dpyinfo = check_x_display_info (display);
4806
4807 HDC hdc; 4848 HDC hdc;
4808 int cap; 4849 double mm_per_pixel;
4809 4850
4810 hdc = GetDC (dpyinfo->root_window); 4851 hdc = GetDC (NULL);
4852 mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE)
4853 / GetDeviceCaps (hdc, HORZRES));
4854 ReleaseDC (NULL, hdc);
4811 4855
4812 cap = GetDeviceCaps (hdc, HORZSIZE); 4856 return make_number (x_display_pixel_width (dpyinfo) * mm_per_pixel + 0.5);
4813
4814 ReleaseDC (dpyinfo->root_window, hdc);
4815
4816 return make_number (cap);
4817} 4857}
4818 4858
4819DEFUN ("x-display-backing-store", Fx_display_backing_store, 4859DEFUN ("x-display-backing-store", Fx_display_backing_store,
@@ -4865,6 +4905,202 @@ If omitted or nil, that stands for the selected frame's display. */)
4865 return Qnil; 4905 return Qnil;
4866} 4906}
4867 4907
4908static BOOL CALLBACK
4909w32_monitor_enum (HMONITOR monitor, HDC hdc, RECT *rcMonitor, LPARAM dwData)
4910{
4911 Lisp_Object *monitor_list = (Lisp_Object *) dwData;
4912
4913 *monitor_list = Fcons (make_save_pointer (monitor), *monitor_list);
4914
4915 return TRUE;
4916}
4917
4918static Lisp_Object
4919w32_display_monitor_attributes_list (void)
4920{
4921 Lisp_Object attributes_list = Qnil, primary_monitor_attributes = Qnil;
4922 Lisp_Object monitor_list = Qnil, monitor_frames, rest, frame;
4923 int i, n_monitors;
4924 HMONITOR *monitors;
4925 struct gcpro gcpro1, gcpro2, gcpro3;
4926
4927 if (!(enum_display_monitors_fn && get_monitor_info_fn
4928 && monitor_from_window_fn))
4929 return Qnil;
4930
4931 if (!enum_display_monitors_fn (NULL, NULL, w32_monitor_enum,
4932 (LPARAM) &monitor_list)
4933 || NILP (monitor_list))
4934 return Qnil;
4935
4936 n_monitors = 0;
4937 for (rest = monitor_list; CONSP (rest); rest = XCDR (rest))
4938 n_monitors++;
4939
4940 monitors = xmalloc (n_monitors * sizeof (*monitors));
4941 for (i = 0; i < n_monitors; i++)
4942 {
4943 monitors[i] = XSAVE_POINTER (XCAR (monitor_list), 0);
4944 monitor_list = XCDR (monitor_list);
4945 }
4946
4947 monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
4948 FOR_EACH_FRAME (rest, frame)
4949 {
4950 struct frame *f = XFRAME (frame);
4951
4952 if (FRAME_W32_P (f) && !EQ (frame, tip_frame))
4953 {
4954 HMONITOR monitor =
4955 monitor_from_window_fn (FRAME_W32_WINDOW (f),
4956 MONITOR_DEFAULT_TO_NEAREST);
4957
4958 for (i = 0; i < n_monitors; i++)
4959 if (monitors[i] == monitor)
4960 break;
4961
4962 if (i < n_monitors)
4963 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
4964 }
4965 }
4966
4967 GCPRO3 (attributes_list, primary_monitor_attributes, monitor_frames);
4968
4969 for (i = 0; i < n_monitors; i++)
4970 {
4971 Lisp_Object geometry, workarea, name, attributes = Qnil;
4972 HDC hdc;
4973 int width_mm, height_mm;
4974 struct MONITOR_INFO_EX mi;
4975
4976 mi.cbSize = sizeof (mi);
4977 if (!get_monitor_info_fn (monitors[i], (struct MONITOR_INFO *) &mi))
4978 continue;
4979
4980 hdc = CreateDCA ("DISPLAY", mi.szDevice, NULL, NULL);
4981 if (hdc == NULL)
4982 continue;
4983 width_mm = GetDeviceCaps (hdc, HORZSIZE);
4984 height_mm = GetDeviceCaps (hdc, VERTSIZE);
4985 DeleteDC (hdc);
4986
4987 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
4988 attributes);
4989
4990 name = DECODE_SYSTEM (make_unibyte_string (mi.szDevice,
4991 strlen (mi.szDevice)));
4992 attributes = Fcons (Fcons (Qname, name), attributes);
4993
4994 attributes = Fcons (Fcons (Qmm_size, list2i (width_mm, height_mm)),
4995 attributes);
4996
4997 workarea = list4i (mi.rcWork.left, mi.rcWork.top,
4998 mi.rcWork.right - mi.rcWork.left,
4999 mi.rcWork.bottom - mi.rcWork.top);
5000 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
5001
5002 geometry = list4i (mi.rcMonitor.left, mi.rcMonitor.top,
5003 mi.rcMonitor.right - mi.rcMonitor.left,
5004 mi.rcMonitor.bottom - mi.rcMonitor.top);
5005 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
5006
5007 if (mi.dwFlags & MONITORINFOF_PRIMARY)
5008 primary_monitor_attributes = attributes;
5009 else
5010 attributes_list = Fcons (attributes, attributes_list);
5011 }
5012
5013 if (!NILP (primary_monitor_attributes))
5014 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
5015
5016 UNGCPRO;
5017
5018 xfree (monitors);
5019
5020 return attributes_list;
5021}
5022
5023static Lisp_Object
5024w32_display_monitor_attributes_list_fallback (struct w32_display_info *dpyinfo)
5025{
5026 Lisp_Object geometry, workarea, frames, rest, frame, attributes = Qnil;
5027 HDC hdc;
5028 double mm_per_pixel;
5029 int pixel_width, pixel_height, width_mm, height_mm;
5030 RECT workarea_rect;
5031
5032 /* Fallback: treat (possibly) multiple physical monitors as if they
5033 formed a single monitor as a whole. This should provide a
5034 consistent result at least on single monitor environments. */
5035 attributes = Fcons (Fcons (Qname, build_string ("combined screen")),
5036 attributes);
5037
5038 frames = Qnil;
5039 FOR_EACH_FRAME (rest, frame)
5040 {
5041 struct frame *f = XFRAME (frame);
5042
5043 if (FRAME_W32_P (f) && !EQ (frame, tip_frame))
5044 frames = Fcons (frame, frames);
5045 }
5046 attributes = Fcons (Fcons (Qframes, frames), attributes);
5047
5048 pixel_width = x_display_pixel_width (dpyinfo);
5049 pixel_height = x_display_pixel_height (dpyinfo);
5050
5051 hdc = GetDC (NULL);
5052 mm_per_pixel = ((double) GetDeviceCaps (hdc, HORZSIZE)
5053 / GetDeviceCaps (hdc, HORZRES));
5054 width_mm = pixel_width * mm_per_pixel + 0.5;
5055 mm_per_pixel = ((double) GetDeviceCaps (hdc, VERTSIZE)
5056 / GetDeviceCaps (hdc, VERTRES));
5057 height_mm = pixel_height * mm_per_pixel + 0.5;
5058 ReleaseDC (NULL, hdc);
5059 attributes = Fcons (Fcons (Qmm_size, list2i (width_mm, height_mm)),
5060 attributes);
5061
5062 /* GetSystemMetrics below may return 0 for Windows 95 or NT 4.0, but
5063 we don't care. */
5064 geometry = list4i (GetSystemMetrics (SM_XVIRTUALSCREEN),
5065 GetSystemMetrics (SM_YVIRTUALSCREEN),
5066 pixel_width, pixel_height);
5067 if (SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0))
5068 workarea = list4i (workarea_rect.left, workarea_rect.top,
5069 workarea_rect.right - workarea_rect.left,
5070 workarea_rect.bottom - workarea_rect.top);
5071 else
5072 workarea = geometry;
5073 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
5074
5075 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
5076
5077 return list1 (attributes);
5078}
5079
5080DEFUN ("w32-display-monitor-attributes-list", Fw32_display_monitor_attributes_list,
5081 Sw32_display_monitor_attributes_list,
5082 0, 1, 0,
5083 doc: /* Return a list of physical monitor attributes on the W32 display DISPLAY.
5084
5085The optional argument DISPLAY specifies which display to ask about.
5086DISPLAY should be either a frame or a display name (a string).
5087If omitted or nil, that stands for the selected frame's display.
5088
5089Internal use only, use `display-monitor-attributes-list' instead. */)
5090 (Lisp_Object display)
5091{
5092 struct w32_display_info *dpyinfo = check_x_display_info (display);
5093 Lisp_Object attributes_list;
5094
5095 block_input ();
5096 attributes_list = w32_display_monitor_attributes_list ();
5097 if (NILP (attributes_list))
5098 attributes_list = w32_display_monitor_attributes_list_fallback (dpyinfo);
5099 unblock_input ();
5100
5101 return attributes_list;
5102}
5103
4868DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0, 5104DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
4869 doc: /* Set the sound generated when the bell is rung. 5105 doc: /* Set the sound generated when the bell is rung.
4870SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent 5106SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent
@@ -7357,6 +7593,10 @@ syms_of_w32fns (void)
7357 DEFSYM (Qcontrol, "control"); 7593 DEFSYM (Qcontrol, "control");
7358 DEFSYM (Qshift, "shift"); 7594 DEFSYM (Qshift, "shift");
7359 DEFSYM (Qfont_param, "font-parameter"); 7595 DEFSYM (Qfont_param, "font-parameter");
7596 DEFSYM (Qgeometry, "geometry");
7597 DEFSYM (Qworkarea, "workarea");
7598 DEFSYM (Qmm_size, "mm-size");
7599 DEFSYM (Qframes, "frames");
7360 /* This is the end of symbol initialization. */ 7600 /* This is the end of symbol initialization. */
7361 7601
7362 7602
@@ -7646,6 +7886,7 @@ only be necessary if the default setting causes problems. */);
7646 7886
7647 defsubr (&Sw32_define_rgb_color); 7887 defsubr (&Sw32_define_rgb_color);
7648 defsubr (&Sw32_default_color_map); 7888 defsubr (&Sw32_default_color_map);
7889 defsubr (&Sw32_display_monitor_attributes_list);
7649 defsubr (&Sw32_send_sys_command); 7890 defsubr (&Sw32_send_sys_command);
7650 defsubr (&Sw32_shell_execute); 7891 defsubr (&Sw32_shell_execute);
7651 defsubr (&Sw32_register_hot_key); 7892 defsubr (&Sw32_register_hot_key);
@@ -7707,6 +7948,8 @@ globals_of_w32fns (void)
7707 GetProcAddress (user32_lib, "GetMonitorInfoA"); 7948 GetProcAddress (user32_lib, "GetMonitorInfoA");
7708 monitor_from_window_fn = (MonitorFromWindow_Proc) 7949 monitor_from_window_fn = (MonitorFromWindow_Proc)
7709 GetProcAddress (user32_lib, "MonitorFromWindow"); 7950 GetProcAddress (user32_lib, "MonitorFromWindow");
7951 enum_display_monitors_fn = (EnumDisplayMonitors_Proc)
7952 GetProcAddress (user32_lib, "EnumDisplayMonitors");
7710 7953
7711 { 7954 {
7712 HMODULE imm32_lib = GetModuleHandle ("imm32.dll"); 7955 HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
diff --git a/src/w32term.c b/src/w32term.c
index d3174c65bf0..732a4f4bfef 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -143,6 +143,15 @@ BOOL (WINAPI *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
143#define WS_EX_LAYERED 0x80000 143#define WS_EX_LAYERED 0x80000
144#endif 144#endif
145 145
146/* SM_CXVIRTUALSCREEN and SM_CYVIRTUALSCREEN are not defined on 95 and
147 NT4. */
148#ifndef SM_CXVIRTUALSCREEN
149#define SM_CXVIRTUALSCREEN 78
150#endif
151#ifndef SM_CYVIRTUALSCREEN
152#define SM_CYVIRTUALSCREEN 79
153#endif
154
146/* This is a frame waiting to be autoraised, within w32_read_socket. */ 155/* This is a frame waiting to be autoraised, within w32_read_socket. */
147struct frame *pending_autoraise_frame; 156struct frame *pending_autoraise_frame;
148 157
@@ -519,18 +528,24 @@ x_set_frame_alpha (struct frame *f)
519int 528int
520x_display_pixel_height (struct w32_display_info *dpyinfo) 529x_display_pixel_height (struct w32_display_info *dpyinfo)
521{ 530{
522 HDC dc = GetDC (NULL); 531 int pixels = GetSystemMetrics (SM_CYVIRTUALSCREEN);
523 int pixels = GetDeviceCaps (dc, VERTRES); 532
524 ReleaseDC (NULL, dc); 533 if (pixels == 0)
534 /* Fallback for Windows 95 or NT 4.0. */
535 pixels = GetSystemMetrics (SM_CYSCREEN);
536
525 return pixels; 537 return pixels;
526} 538}
527 539
528int 540int
529x_display_pixel_width (struct w32_display_info *dpyinfo) 541x_display_pixel_width (struct w32_display_info *dpyinfo)
530{ 542{
531 HDC dc = GetDC (NULL); 543 int pixels = GetSystemMetrics (SM_CXVIRTUALSCREEN);
532 int pixels = GetDeviceCaps (dc, HORZRES); 544
533 ReleaseDC (NULL, dc); 545 if (pixels == 0)
546 /* Fallback for Windows 95 or NT 4.0. */
547 pixels = GetSystemMetrics (SM_CXSCREEN);
548
534 return pixels; 549 return pixels;
535} 550}
536 551
@@ -5159,7 +5174,10 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
5159 the current matrix is invalid or such, give up. */ 5174 the current matrix is invalid or such, give up. */
5160 cursor_glyph = get_phys_cursor_glyph (w); 5175 cursor_glyph = get_phys_cursor_glyph (w);
5161 if (cursor_glyph == NULL) 5176 if (cursor_glyph == NULL)
5162 return; 5177 {
5178 DeleteObject (hb);
5179 return;
5180 }
5163 5181
5164 /* Compute frame-relative coordinates for phys cursor. */ 5182 /* Compute frame-relative coordinates for phys cursor. */
5165 get_phys_cursor_geometry (w, row, cursor_glyph, &left, &top, &h); 5183 get_phys_cursor_geometry (w, row, cursor_glyph, &left, &top, &h);
@@ -6606,7 +6624,7 @@ w32_initialize (void)
6606 } 6624 }
6607 6625
6608#ifdef CYGWIN 6626#ifdef CYGWIN
6609 if ((w32_message_fd = open ("/dev/windows", O_RDWR | O_CLOEXEC)) == -1) 6627 if ((w32_message_fd = emacs_open ("/dev/windows", O_RDWR, 0)) == -1)
6610 fatal ("opening /dev/windows: %s", strerror (errno)); 6628 fatal ("opening /dev/windows: %s", strerror (errno));
6611#endif /* CYGWIN */ 6629#endif /* CYGWIN */
6612 6630
diff --git a/src/window.c b/src/window.c
index f02aa1d89a0..5c5d2b8e138 100644
--- a/src/window.c
+++ b/src/window.c
@@ -4374,6 +4374,8 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4374 int vscrolled = 0; 4374 int vscrolled = 0;
4375 int x, y, rtop, rbot, rowh, vpos; 4375 int x, y, rtop, rbot, rowh, vpos;
4376 void *itdata = NULL; 4376 void *itdata = NULL;
4377 int window_total_lines;
4378 int frame_line_height = default_line_pixel_height (w);
4377 4379
4378 SET_TEXT_POS_FROM_MARKER (start, w->start); 4380 SET_TEXT_POS_FROM_MARKER (start, w->start);
4379 /* Scrolling a minibuffer window via scroll bar when the echo area 4381 /* Scrolling a minibuffer window via scroll bar when the echo area
@@ -4417,7 +4419,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4417 if (rtop || rbot) /* partially visible */ 4419 if (rtop || rbot) /* partially visible */
4418 { 4420 {
4419 int px; 4421 int px;
4420 int dy = WINDOW_FRAME_LINE_HEIGHT (w); 4422 int dy = frame_line_height;
4421 if (whole) 4423 if (whole)
4422 dy = max ((window_box_height (w) 4424 dy = max ((window_box_height (w)
4423 - next_screen_context_lines * dy), 4425 - next_screen_context_lines * dy),
@@ -4503,7 +4505,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4503 if (whole) 4505 if (whole)
4504 { 4506 {
4505 ptrdiff_t start_pos = IT_CHARPOS (it); 4507 ptrdiff_t start_pos = IT_CHARPOS (it);
4506 int dy = WINDOW_FRAME_LINE_HEIGHT (w); 4508 int dy = frame_line_height;
4507 dy = max ((window_box_height (w) 4509 dy = max ((window_box_height (w)
4508 - next_screen_context_lines * dy), 4510 - next_screen_context_lines * dy),
4509 dy) * n; 4511 dy) * n;
@@ -4620,10 +4622,12 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4620 /* Move PT out of scroll margins. 4622 /* Move PT out of scroll margins.
4621 This code wants current_y to be zero at the window start position 4623 This code wants current_y to be zero at the window start position
4622 even if there is a header line. */ 4624 even if there is a header line. */
4625 window_total_lines
4626 = w->total_lines * WINDOW_FRAME_LINE_HEIGHT (w) / frame_line_height;
4623 this_scroll_margin = max (0, scroll_margin); 4627 this_scroll_margin = max (0, scroll_margin);
4624 this_scroll_margin 4628 this_scroll_margin
4625 = min (this_scroll_margin, w->total_lines / 4); 4629 = min (this_scroll_margin, window_total_lines / 4);
4626 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f); 4630 this_scroll_margin *= frame_line_height;
4627 4631
4628 if (n > 0) 4632 if (n > 0)
4629 { 4633 {
diff --git a/src/xdisp.c b/src/xdisp.c
index 88a806fa268..9aae37d48c1 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -1239,6 +1239,52 @@ Value is the height in pixels of the line at point. */)
1239 return make_number (line_bottom_y (&it)); 1239 return make_number (line_bottom_y (&it));
1240} 1240}
1241 1241
1242/* Return the default pixel height of text lines in window W. The
1243 value is the canonical height of the W frame's default font, plus
1244 any extra space required by the line-spacing variable or frame
1245 parameter.
1246
1247 Implementation note: this ignores any line-spacing text properties
1248 put on the newline characters. This is because those properties
1249 only affect the _screen_ line ending in the newline (i.e., in a
1250 continued line, only the last screen line will be affected), which
1251 means only a small number of lines in a buffer can ever use this
1252 feature. Since this function is used to compute the default pixel
1253 equivalent of text lines in a window, we can safely ignore those
1254 few lines. For the same reasons, we ignore the line-height
1255 properties. */
1256int
1257default_line_pixel_height (struct window *w)
1258{
1259 struct frame *f = WINDOW_XFRAME (w);
1260 int height = FRAME_LINE_HEIGHT (f);
1261
1262 if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
1263 {
1264 struct buffer *b = XBUFFER (w->contents);
1265 Lisp_Object val = BVAR (b, extra_line_spacing);
1266
1267 if (NILP (val))
1268 val = BVAR (&buffer_defaults, extra_line_spacing);
1269 if (!NILP (val))
1270 {
1271 if (RANGED_INTEGERP (0, val, INT_MAX))
1272 height += XFASTINT (val);
1273 else if (FLOATP (val))
1274 {
1275 int addon = XFLOAT_DATA (val) * height + 0.5;
1276
1277 if (addon >= 0)
1278 height += addon;
1279 }
1280 }
1281 else
1282 height += f->extra_line_spacing;
1283 }
1284
1285 return height;
1286}
1287
1242/* Subroutine of pos_visible_p below. Extracts a display string, if 1288/* Subroutine of pos_visible_p below. Extracts a display string, if
1243 any, from the display spec given as its argument. */ 1289 any, from the display spec given as its argument. */
1244static Lisp_Object 1290static Lisp_Object
@@ -1373,8 +1419,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1373 struct it save_it = it; 1419 struct it save_it = it;
1374 /* Why 10? because we don't know how many canonical lines 1420 /* Why 10? because we don't know how many canonical lines
1375 will the height of the next line(s) be. So we guess. */ 1421 will the height of the next line(s) be. So we guess. */
1376 int ten_more_lines = 1422 int ten_more_lines = 10 * default_line_pixel_height (w);
1377 10 * FRAME_LINE_HEIGHT (XFRAME (WINDOW_FRAME (w)));
1378 1423
1379 move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1, 1424 move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
1380 MOVE_TO_POS | MOVE_TO_Y); 1425 MOVE_TO_POS | MOVE_TO_Y);
@@ -9112,7 +9157,7 @@ move_it_vertically_backward (struct it *it, int dy)
9112 start_pos = IT_CHARPOS (*it); 9157 start_pos = IT_CHARPOS (*it);
9113 9158
9114 /* Estimate how many newlines we must move back. */ 9159 /* Estimate how many newlines we must move back. */
9115 nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f)); 9160 nlines = max (1, dy / default_line_pixel_height (it->w));
9116 if (it->line_wrap == TRUNCATE) 9161 if (it->line_wrap == TRUNCATE)
9117 pos_limit = BEGV; 9162 pos_limit = BEGV;
9118 else 9163 else
@@ -12600,6 +12645,7 @@ static void debug_method_add (struct window *, char const *, ...)
12600static void 12645static void
12601debug_method_add (struct window *w, char const *fmt, ...) 12646debug_method_add (struct window *w, char const *fmt, ...)
12602{ 12647{
12648 void *ptr = w;
12603 char *method = w->desired_matrix->method; 12649 char *method = w->desired_matrix->method;
12604 int len = strlen (method); 12650 int len = strlen (method);
12605 int size = sizeof w->desired_matrix->method; 12651 int size = sizeof w->desired_matrix->method;
@@ -12618,7 +12664,7 @@ debug_method_add (struct window *w, char const *fmt, ...)
12618 12664
12619 if (trace_redisplay_p) 12665 if (trace_redisplay_p)
12620 fprintf (stderr, "%p (%s): %s\n", 12666 fprintf (stderr, "%p (%s): %s\n",
12621 w, 12667 ptr,
12622 ((BUFFERP (w->contents) 12668 ((BUFFERP (w->contents)
12623 && STRINGP (BVAR (XBUFFER (w->contents), name))) 12669 && STRINGP (BVAR (XBUFFER (w->contents), name)))
12624 ? SSDATA (BVAR (XBUFFER (w->contents), name)) 12670 ? SSDATA (BVAR (XBUFFER (w->contents), name))
@@ -14599,6 +14645,9 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
14599 Lisp_Object aggressive; 14645 Lisp_Object aggressive;
14600 /* We will never try scrolling more than this number of lines. */ 14646 /* We will never try scrolling more than this number of lines. */
14601 int scroll_limit = SCROLL_LIMIT; 14647 int scroll_limit = SCROLL_LIMIT;
14648 int frame_line_height = default_line_pixel_height (w);
14649 int window_total_lines
14650 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
14602 14651
14603#ifdef GLYPH_DEBUG 14652#ifdef GLYPH_DEBUG
14604 debug_method_add (w, "try_scrolling"); 14653 debug_method_add (w, "try_scrolling");
@@ -14609,8 +14658,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
14609 /* Compute scroll margin height in pixels. We scroll when point is 14658 /* Compute scroll margin height in pixels. We scroll when point is
14610 within this distance from the top or bottom of the window. */ 14659 within this distance from the top or bottom of the window. */
14611 if (scroll_margin > 0) 14660 if (scroll_margin > 0)
14612 this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4) 14661 this_scroll_margin = min (scroll_margin, window_total_lines / 4)
14613 * FRAME_LINE_HEIGHT (f); 14662 * frame_line_height;
14614 else 14663 else
14615 this_scroll_margin = 0; 14664 this_scroll_margin = 0;
14616 14665
@@ -14621,19 +14670,19 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
14621 if (arg_scroll_conservatively > scroll_limit) 14670 if (arg_scroll_conservatively > scroll_limit)
14622 { 14671 {
14623 arg_scroll_conservatively = scroll_limit + 1; 14672 arg_scroll_conservatively = scroll_limit + 1;
14624 scroll_max = scroll_limit * FRAME_LINE_HEIGHT (f); 14673 scroll_max = scroll_limit * frame_line_height;
14625 } 14674 }
14626 else if (scroll_step || arg_scroll_conservatively || temp_scroll_step) 14675 else if (scroll_step || arg_scroll_conservatively || temp_scroll_step)
14627 /* Compute how much we should try to scroll maximally to bring 14676 /* Compute how much we should try to scroll maximally to bring
14628 point into view. */ 14677 point into view. */
14629 scroll_max = (max (scroll_step, 14678 scroll_max = (max (scroll_step,
14630 max (arg_scroll_conservatively, temp_scroll_step)) 14679 max (arg_scroll_conservatively, temp_scroll_step))
14631 * FRAME_LINE_HEIGHT (f)); 14680 * frame_line_height);
14632 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively)) 14681 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
14633 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))) 14682 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
14634 /* We're trying to scroll because of aggressive scrolling but no 14683 /* We're trying to scroll because of aggressive scrolling but no
14635 scroll_step is set. Choose an arbitrary one. */ 14684 scroll_step is set. Choose an arbitrary one. */
14636 scroll_max = 10 * FRAME_LINE_HEIGHT (f); 14685 scroll_max = 10 * frame_line_height;
14637 else 14686 else
14638 scroll_max = 0; 14687 scroll_max = 0;
14639 14688
@@ -14648,7 +14697,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
14648 either that ypos or PT, whichever comes first. */ 14697 either that ypos or PT, whichever comes first. */
14649 start_display (&it, w, startp); 14698 start_display (&it, w, startp);
14650 scroll_margin_y = it.last_visible_y - this_scroll_margin 14699 scroll_margin_y = it.last_visible_y - this_scroll_margin
14651 - FRAME_LINE_HEIGHT (f) * extra_scroll_margin_lines; 14700 - frame_line_height * extra_scroll_margin_lines;
14652 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1, 14701 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
14653 (MOVE_TO_POS | MOVE_TO_Y)); 14702 (MOVE_TO_POS | MOVE_TO_Y));
14654 14703
@@ -14660,7 +14709,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
14660 the user limited scrolling by a small number of lines, but 14709 the user limited scrolling by a small number of lines, but
14661 always finds PT if scroll_conservatively is set to a large 14710 always finds PT if scroll_conservatively is set to a large
14662 number, such as most-positive-fixnum. */ 14711 number, such as most-positive-fixnum. */
14663 int slack = max (scroll_max, 10 * FRAME_LINE_HEIGHT (f)); 14712 int slack = max (scroll_max, 10 * frame_line_height);
14664 int y_to_move = it.last_visible_y + slack; 14713 int y_to_move = it.last_visible_y + slack;
14665 14714
14666 /* Compute the distance from the scroll margin to PT or to 14715 /* Compute the distance from the scroll margin to PT or to
@@ -14687,8 +14736,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
14687 move it down by scroll_step. */ 14736 move it down by scroll_step. */
14688 if (arg_scroll_conservatively) 14737 if (arg_scroll_conservatively)
14689 amount_to_scroll 14738 amount_to_scroll
14690 = min (max (dy, FRAME_LINE_HEIGHT (f)), 14739 = min (max (dy, frame_line_height),
14691 FRAME_LINE_HEIGHT (f) * arg_scroll_conservatively); 14740 frame_line_height * arg_scroll_conservatively);
14692 else if (scroll_step || temp_scroll_step) 14741 else if (scroll_step || temp_scroll_step)
14693 amount_to_scroll = scroll_max; 14742 amount_to_scroll = scroll_max;
14694 else 14743 else
@@ -14785,7 +14834,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
14785 start_display (&it, w, pos); 14834 start_display (&it, w, pos);
14786 y0 = it.current_y; 14835 y0 = it.current_y;
14787 y_to_move = max (it.last_visible_y, 14836 y_to_move = max (it.last_visible_y,
14788 max (scroll_max, 10 * FRAME_LINE_HEIGHT (f))); 14837 max (scroll_max, 10 * frame_line_height));
14789 move_it_to (&it, CHARPOS (scroll_margin_pos), 0, 14838 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
14790 y_to_move, -1, 14839 y_to_move, -1,
14791 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); 14840 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
@@ -14801,7 +14850,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
14801 start_display (&it, w, startp); 14850 start_display (&it, w, startp);
14802 14851
14803 if (arg_scroll_conservatively) 14852 if (arg_scroll_conservatively)
14804 amount_to_scroll = max (dy, FRAME_LINE_HEIGHT (f) * 14853 amount_to_scroll = max (dy, frame_line_height *
14805 max (scroll_step, temp_scroll_step)); 14854 max (scroll_step, temp_scroll_step));
14806 else if (scroll_step || temp_scroll_step) 14855 else if (scroll_step || temp_scroll_step)
14807 amount_to_scroll = scroll_max; 14856 amount_to_scroll = scroll_max;
@@ -15021,6 +15070,9 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
15021 { 15070 {
15022 int this_scroll_margin, top_scroll_margin; 15071 int this_scroll_margin, top_scroll_margin;
15023 struct glyph_row *row = NULL; 15072 struct glyph_row *row = NULL;
15073 int frame_line_height = default_line_pixel_height (w);
15074 int window_total_lines
15075 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
15024 15076
15025#ifdef GLYPH_DEBUG 15077#ifdef GLYPH_DEBUG
15026 debug_method_add (w, "cursor movement"); 15078 debug_method_add (w, "cursor movement");
@@ -15030,8 +15082,8 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
15030 of the window. This is a pixel value. */ 15082 of the window. This is a pixel value. */
15031 if (scroll_margin > 0) 15083 if (scroll_margin > 0)
15032 { 15084 {
15033 this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4); 15085 this_scroll_margin = min (scroll_margin, window_total_lines / 4);
15034 this_scroll_margin *= FRAME_LINE_HEIGHT (f); 15086 this_scroll_margin *= frame_line_height;
15035 } 15087 }
15036 else 15088 else
15037 this_scroll_margin = 0; 15089 this_scroll_margin = 0;
@@ -15373,6 +15425,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15373 int centering_position = -1; 15425 int centering_position = -1;
15374 int last_line_misfit = 0; 15426 int last_line_misfit = 0;
15375 ptrdiff_t beg_unchanged, end_unchanged; 15427 ptrdiff_t beg_unchanged, end_unchanged;
15428 int frame_line_height;
15376 15429
15377 SET_TEXT_POS (lpoint, PT, PT_BYTE); 15430 SET_TEXT_POS (lpoint, PT, PT_BYTE);
15378 opoint = lpoint; 15431 opoint = lpoint;
@@ -15387,6 +15440,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15387 15440
15388 restart: 15441 restart:
15389 reconsider_clip_changes (w, buffer); 15442 reconsider_clip_changes (w, buffer);
15443 frame_line_height = default_line_pixel_height (w);
15390 15444
15391 /* Has the mode line to be updated? */ 15445 /* Has the mode line to be updated? */
15392 update_mode_line = (w->update_mode_line 15446 update_mode_line = (w->update_mode_line
@@ -15622,8 +15676,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15622 /* Some people insist on not letting point enter the scroll 15676 /* Some people insist on not letting point enter the scroll
15623 margin, even though this part handles windows that didn't 15677 margin, even though this part handles windows that didn't
15624 scroll at all. */ 15678 scroll at all. */
15625 int margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4); 15679 int window_total_lines
15626 int pixel_margin = margin * FRAME_LINE_HEIGHT (f); 15680 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
15681 int margin = min (scroll_margin, window_total_lines / 4);
15682 int pixel_margin = margin * frame_line_height;
15627 bool header_line = WINDOW_WANTS_HEADER_LINE_P (w); 15683 bool header_line = WINDOW_WANTS_HEADER_LINE_P (w);
15628 15684
15629 /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop 15685 /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop
@@ -15634,7 +15690,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15634 new_vpos 15690 new_vpos
15635 = pixel_margin + (header_line 15691 = pixel_margin + (header_line
15636 ? CURRENT_HEADER_LINE_HEIGHT (w) 15692 ? CURRENT_HEADER_LINE_HEIGHT (w)
15637 : 0) + FRAME_LINE_HEIGHT (f); 15693 : 0) + frame_line_height;
15638 else 15694 else
15639 { 15695 {
15640 int window_height = window_box_height (w); 15696 int window_height = window_box_height (w);
@@ -15883,9 +15939,11 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15883 it.current_y = it.last_visible_y; 15939 it.current_y = it.last_visible_y;
15884 if (centering_position < 0) 15940 if (centering_position < 0)
15885 { 15941 {
15942 int window_total_lines
15943 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
15886 int margin = 15944 int margin =
15887 scroll_margin > 0 15945 scroll_margin > 0
15888 ? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4) 15946 ? min (scroll_margin, window_total_lines / 4)
15889 : 0; 15947 : 0;
15890 ptrdiff_t margin_pos = CHARPOS (startp); 15948 ptrdiff_t margin_pos = CHARPOS (startp);
15891 Lisp_Object aggressive; 15949 Lisp_Object aggressive;
@@ -15907,7 +15965,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15907 15965
15908 SAVE_IT (it1, it, it1data); 15966 SAVE_IT (it1, it, it1data);
15909 start_display (&it1, w, startp); 15967 start_display (&it1, w, startp);
15910 move_it_vertically (&it1, margin * FRAME_LINE_HEIGHT (f)); 15968 move_it_vertically (&it1, margin * frame_line_height);
15911 margin_pos = IT_CHARPOS (it1); 15969 margin_pos = IT_CHARPOS (it1);
15912 RESTORE_IT (&it, &it, it1data); 15970 RESTORE_IT (&it, &it, it1data);
15913 } 15971 }
@@ -15943,15 +16001,15 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
15943 if (pt_offset) 16001 if (pt_offset)
15944 centering_position -= pt_offset; 16002 centering_position -= pt_offset;
15945 centering_position -= 16003 centering_position -=
15946 FRAME_LINE_HEIGHT (f) * (1 + margin + (last_line_misfit != 0)) 16004 frame_line_height * (1 + margin + (last_line_misfit != 0))
15947 + WINDOW_HEADER_LINE_HEIGHT (w); 16005 + WINDOW_HEADER_LINE_HEIGHT (w);
15948 /* Don't let point enter the scroll margin near top of 16006 /* Don't let point enter the scroll margin near top of
15949 the window. */ 16007 the window. */
15950 if (centering_position < margin * FRAME_LINE_HEIGHT (f)) 16008 if (centering_position < margin * frame_line_height)
15951 centering_position = margin * FRAME_LINE_HEIGHT (f); 16009 centering_position = margin * frame_line_height;
15952 } 16010 }
15953 else 16011 else
15954 centering_position = margin * FRAME_LINE_HEIGHT (f) + pt_offset; 16012 centering_position = margin * frame_line_height + pt_offset;
15955 } 16013 }
15956 else 16014 else
15957 /* Set the window start half the height of the window backward 16015 /* Set the window start half the height of the window backward
@@ -16056,11 +16114,13 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
16056 make that row fully visible and out of the margin. */ 16114 make that row fully visible and out of the margin. */
16057 if (scroll_conservatively > SCROLL_LIMIT) 16115 if (scroll_conservatively > SCROLL_LIMIT)
16058 { 16116 {
16117 int window_total_lines
16118 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) * frame_line_height;
16059 int margin = 16119 int margin =
16060 scroll_margin > 0 16120 scroll_margin > 0
16061 ? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4) 16121 ? min (scroll_margin, window_total_lines / 4)
16062 : 0; 16122 : 0;
16063 int move_down = w->cursor.vpos >= WINDOW_TOTAL_LINES (w) / 2; 16123 int move_down = w->cursor.vpos >= window_total_lines / 2;
16064 16124
16065 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1)); 16125 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
16066 clear_glyph_matrix (w->desired_matrix); 16126 clear_glyph_matrix (w->desired_matrix);
@@ -16247,6 +16307,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
16247 struct it it; 16307 struct it it;
16248 struct glyph_row *last_text_row = NULL; 16308 struct glyph_row *last_text_row = NULL;
16249 struct frame *f = XFRAME (w->frame); 16309 struct frame *f = XFRAME (w->frame);
16310 int frame_line_height = default_line_pixel_height (w);
16250 16311
16251 /* Make POS the new window start. */ 16312 /* Make POS the new window start. */
16252 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos)); 16313 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
@@ -16279,11 +16340,13 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
16279 && !MINI_WINDOW_P (w)) 16340 && !MINI_WINDOW_P (w))
16280 { 16341 {
16281 int this_scroll_margin; 16342 int this_scroll_margin;
16343 int window_total_lines
16344 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
16282 16345
16283 if (scroll_margin > 0) 16346 if (scroll_margin > 0)
16284 { 16347 {
16285 this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4); 16348 this_scroll_margin = min (scroll_margin, window_total_lines / 4);
16286 this_scroll_margin *= FRAME_LINE_HEIGHT (f); 16349 this_scroll_margin *= frame_line_height;
16287 } 16350 }
16288 else 16351 else
16289 this_scroll_margin = 0; 16352 this_scroll_margin = 0;
@@ -17598,10 +17661,13 @@ try_window_id (struct window *w)
17598 /* Don't let the cursor end in the scroll margins. */ 17661 /* Don't let the cursor end in the scroll margins. */
17599 { 17662 {
17600 int this_scroll_margin, cursor_height; 17663 int this_scroll_margin, cursor_height;
17664 int frame_line_height = default_line_pixel_height (w);
17665 int window_total_lines
17666 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (it.f) / frame_line_height;
17601 17667
17602 this_scroll_margin = 17668 this_scroll_margin =
17603 max (0, min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)); 17669 max (0, min (scroll_margin, window_total_lines / 4));
17604 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f); 17670 this_scroll_margin *= frame_line_height;
17605 cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height; 17671 cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
17606 17672
17607 if ((w->cursor.y < this_scroll_margin 17673 if ((w->cursor.y < this_scroll_margin
diff --git a/src/xfaces.c b/src/xfaces.c
index b2ace1be14e..4b42cb7dc40 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -200,10 +200,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
200 used to fill in unspecified attributes of the default face. */ 200 used to fill in unspecified attributes of the default face. */
201 201
202#include <config.h> 202#include <config.h>
203#include <stdio.h> 203#include "sysstdio.h"
204#include <sys/types.h> 204#include <sys/types.h>
205#include <sys/stat.h> 205#include <sys/stat.h>
206#include <stdio.h> /* This needs to be before termchar.h */
207 206
208#include "lisp.h" 207#include "lisp.h"
209#include "character.h" 208#include "character.h"
@@ -6291,7 +6290,7 @@ where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
6291 CHECK_STRING (filename); 6290 CHECK_STRING (filename);
6292 abspath = Fexpand_file_name (filename, Qnil); 6291 abspath = Fexpand_file_name (filename, Qnil);
6293 6292
6294 fp = fopen (SSDATA (abspath), "rt"); 6293 fp = emacs_fopen (SSDATA (abspath), "rt");
6295 if (fp) 6294 if (fp)
6296 { 6295 {
6297 char buf[512]; 6296 char buf[512];
diff --git a/src/xrdb.c b/src/xrdb.c
index c25c25d6f33..7c9cd53fa8c 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -634,10 +634,7 @@ member (char *elt, List list)
634static void 634static void
635fatal (char *msg, char *prog) 635fatal (char *msg, char *prog)
636{ 636{
637 if (errno) 637 fprintf (stderr, msg, prog);
638 perror (prog);
639
640 (void) fprintf (stderr, msg, prog);
641 exit (1); 638 exit (1);
642} 639}
643 640
diff --git a/src/xsettings.c b/src/xsettings.c
index f48c49dbafe..45f8435d9f4 100644
--- a/src/xsettings.c
+++ b/src/xsettings.c
@@ -170,7 +170,7 @@ enum {
170 SEEN_HINTSTYLE = 0x10, 170 SEEN_HINTSTYLE = 0x10,
171 SEEN_DPI = 0x20, 171 SEEN_DPI = 0x20,
172 SEEN_FONT = 0x40, 172 SEEN_FONT = 0x40,
173 SEEN_TB_STYLE = 0x80, 173 SEEN_TB_STYLE = 0x80
174}; 174};
175struct xsettings 175struct xsettings
176{ 176{
@@ -687,7 +687,7 @@ apply_xft_settings (struct x_display_info *dpyinfo,
687 { 687 {
688 static char const format[] = 688 static char const format[] =
689 "Antialias: %d, Hinting: %d, RGBA: %d, LCDFilter: %d, " 689 "Antialias: %d, Hinting: %d, RGBA: %d, LCDFilter: %d, "
690 "Hintstyle: %d, DPI: %lf"; 690 "Hintstyle: %d, DPI: %f";
691 enum 691 enum
692 { 692 {
693 d_formats = 5, 693 d_formats = 5,
@@ -696,7 +696,7 @@ apply_xft_settings (struct x_display_info *dpyinfo,
696 max_f_integer_digits = DBL_MAX_10_EXP + 1, 696 max_f_integer_digits = DBL_MAX_10_EXP + 1,
697 f_precision = 6, 697 f_precision = 6,
698 lf_growth = (sizeof "-." + max_f_integer_digits + f_precision 698 lf_growth = (sizeof "-." + max_f_integer_digits + f_precision
699 - sizeof "%lf") 699 - sizeof "%f")
700 }; 700 };
701 char buf[sizeof format + d_formats * d_growth + lf_formats * lf_growth]; 701 char buf[sizeof format + d_formats * d_growth + lf_formats * lf_growth];
702 702
diff --git a/src/xterm.c b/src/xterm.c
index 3755b478dbc..547bdbe8333 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -72,7 +72,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
72#include "atimer.h" 72#include "atimer.h"
73#include "keymap.h" 73#include "keymap.h"
74#include "font.h" 74#include "font.h"
75#include "fontset.h"
76#include "xsettings.h" 75#include "xsettings.h"
77#include "xgselect.h" 76#include "xgselect.h"
78#include "sysselect.h" 77#include "sysselect.h"
@@ -2651,7 +2650,10 @@ x_draw_underwave (struct glyph_string *s)
2651 2650
2652 /* Find and set clipping rectangle */ 2651 /* Find and set clipping rectangle */
2653 2652
2654 wave_clip = (XRectangle){ x0, y0, width, wave_height }; 2653 wave_clip.x = x0;
2654 wave_clip.y = y0;
2655 wave_clip.width = width;
2656 wave_clip.height = wave_height;
2655 get_glyph_string_clip_rect (s, &string_clip); 2657 get_glyph_string_clip_rect (s, &string_clip);
2656 2658
2657 if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip)) 2659 if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
@@ -10210,71 +10212,73 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
10210 } 10212 }
10211 10213
10212 { 10214 {
10213 const struct 10215 static const struct
10214 { 10216 {
10215 const char *name; 10217 const char *name;
10216 Atom *atom; 10218 int offset;
10217 } atom_refs[] = { 10219 } atom_refs[] = {
10218 { "WM_PROTOCOLS", &dpyinfo->Xatom_wm_protocols }, 10220#define ATOM_REFS_INIT(string, member) \
10219 { "WM_TAKE_FOCUS", &dpyinfo->Xatom_wm_take_focus }, 10221 { string, offsetof (struct x_display_info, member) },
10220 { "WM_SAVE_YOURSELF", &dpyinfo->Xatom_wm_save_yourself }, 10222 ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols)
10221 { "WM_DELETE_WINDOW", &dpyinfo->Xatom_wm_delete_window }, 10223 ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus)
10222 { "WM_CHANGE_STATE", &dpyinfo->Xatom_wm_change_state }, 10224 ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself)
10223 { "WM_CONFIGURE_DENIED", &dpyinfo->Xatom_wm_configure_denied }, 10225 ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window)
10224 { "WM_MOVED", &dpyinfo->Xatom_wm_window_moved }, 10226 ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state)
10225 { "WM_CLIENT_LEADER", &dpyinfo->Xatom_wm_client_leader }, 10227 ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied)
10226 { "Editres", &dpyinfo->Xatom_editres }, 10228 ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved)
10227 { "CLIPBOARD", &dpyinfo->Xatom_CLIPBOARD }, 10229 ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader)
10228 { "TIMESTAMP", &dpyinfo->Xatom_TIMESTAMP }, 10230 ATOM_REFS_INIT ("Editres", Xatom_editres)
10229 { "TEXT", &dpyinfo->Xatom_TEXT }, 10231 ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD)
10230 { "COMPOUND_TEXT", &dpyinfo->Xatom_COMPOUND_TEXT }, 10232 ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP)
10231 { "UTF8_STRING", &dpyinfo->Xatom_UTF8_STRING }, 10233 ATOM_REFS_INIT ("TEXT", Xatom_TEXT)
10232 { "DELETE", &dpyinfo->Xatom_DELETE }, 10234 ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT)
10233 { "MULTIPLE", &dpyinfo->Xatom_MULTIPLE }, 10235 ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING)
10234 { "INCR", &dpyinfo->Xatom_INCR }, 10236 ATOM_REFS_INIT ("DELETE", Xatom_DELETE)
10235 { "_EMACS_TMP_", &dpyinfo->Xatom_EMACS_TMP }, 10237 ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE)
10236 { "TARGETS", &dpyinfo->Xatom_TARGETS }, 10238 ATOM_REFS_INIT ("INCR", Xatom_INCR)
10237 { "NULL", &dpyinfo->Xatom_NULL }, 10239 ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP)
10238 { "ATOM", &dpyinfo->Xatom_ATOM }, 10240 ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS)
10239 { "ATOM_PAIR", &dpyinfo->Xatom_ATOM_PAIR }, 10241 ATOM_REFS_INIT ("NULL", Xatom_NULL)
10240 { "CLIPBOARD_MANAGER", &dpyinfo->Xatom_CLIPBOARD_MANAGER }, 10242 ATOM_REFS_INIT ("ATOM", Xatom_ATOM)
10241 { "_XEMBED_INFO", &dpyinfo->Xatom_XEMBED_INFO }, 10243 ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR)
10244 ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER)
10245 ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO)
10242 /* For properties of font. */ 10246 /* For properties of font. */
10243 { "PIXEL_SIZE", &dpyinfo->Xatom_PIXEL_SIZE }, 10247 ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE)
10244 { "AVERAGE_WIDTH", &dpyinfo->Xatom_AVERAGE_WIDTH }, 10248 ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH)
10245 { "_MULE_BASELINE_OFFSET", &dpyinfo->Xatom_MULE_BASELINE_OFFSET }, 10249 ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET)
10246 { "_MULE_RELATIVE_COMPOSE", &dpyinfo->Xatom_MULE_RELATIVE_COMPOSE }, 10250 ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE)
10247 { "_MULE_DEFAULT_ASCENT", &dpyinfo->Xatom_MULE_DEFAULT_ASCENT }, 10251 ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT)
10248 /* Ghostscript support. */ 10252 /* Ghostscript support. */
10249 { "DONE", &dpyinfo->Xatom_DONE }, 10253 ATOM_REFS_INIT ("DONE", Xatom_DONE)
10250 { "PAGE", &dpyinfo->Xatom_PAGE }, 10254 ATOM_REFS_INIT ("PAGE", Xatom_PAGE)
10251 { "SCROLLBAR", &dpyinfo->Xatom_Scrollbar }, 10255 ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar)
10252 { "_XEMBED", &dpyinfo->Xatom_XEMBED }, 10256 ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED)
10253 /* EWMH */ 10257 /* EWMH */
10254 { "_NET_WM_STATE", &dpyinfo->Xatom_net_wm_state }, 10258 ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state)
10255 { "_NET_WM_STATE_FULLSCREEN", &dpyinfo->Xatom_net_wm_state_fullscreen }, 10259 ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen)
10256 { "_NET_WM_STATE_MAXIMIZED_HORZ", 10260 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ",
10257 &dpyinfo->Xatom_net_wm_state_maximized_horz }, 10261 Xatom_net_wm_state_maximized_horz)
10258 { "_NET_WM_STATE_MAXIMIZED_VERT", 10262 ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT",
10259 &dpyinfo->Xatom_net_wm_state_maximized_vert }, 10263 Xatom_net_wm_state_maximized_vert)
10260 { "_NET_WM_STATE_STICKY", &dpyinfo->Xatom_net_wm_state_sticky }, 10264 ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky)
10261 { "_NET_WM_STATE_HIDDEN", &dpyinfo->Xatom_net_wm_state_hidden }, 10265 ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden)
10262 { "_NET_WM_WINDOW_TYPE", &dpyinfo->Xatom_net_window_type }, 10266 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type)
10263 { "_NET_WM_WINDOW_TYPE_TOOLTIP", 10267 ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP",
10264 &dpyinfo->Xatom_net_window_type_tooltip }, 10268 Xatom_net_window_type_tooltip)
10265 { "_NET_WM_ICON_NAME", &dpyinfo->Xatom_net_wm_icon_name }, 10269 ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name)
10266 { "_NET_WM_NAME", &dpyinfo->Xatom_net_wm_name }, 10270 ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name)
10267 { "_NET_SUPPORTED", &dpyinfo->Xatom_net_supported }, 10271 ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported)
10268 { "_NET_SUPPORTING_WM_CHECK", &dpyinfo->Xatom_net_supporting_wm_check }, 10272 ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check)
10269 { "_NET_WM_WINDOW_OPACITY", &dpyinfo->Xatom_net_wm_window_opacity }, 10273 ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity)
10270 { "_NET_ACTIVE_WINDOW", &dpyinfo->Xatom_net_active_window }, 10274 ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window)
10271 { "_NET_FRAME_EXTENTS", &dpyinfo->Xatom_net_frame_extents }, 10275 ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents)
10272 { "_NET_CURRENT_DESKTOP", &dpyinfo->Xatom_net_current_desktop }, 10276 ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop)
10273 { "_NET_WORKAREA", &dpyinfo->Xatom_net_workarea }, 10277 ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea)
10274 /* Session management */ 10278 /* Session management */
10275 { "SM_CLIENT_ID", &dpyinfo->Xatom_SM_CLIENT_ID }, 10279 ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
10276 { "_XSETTINGS_SETTINGS", &dpyinfo->Xatom_xsettings_prop }, 10280 ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
10277 { "MANAGER", &dpyinfo->Xatom_xsettings_mgr }, 10281 ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr)
10278 }; 10282 };
10279 10283
10280 int i; 10284 int i;
@@ -10299,7 +10303,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
10299 False, atoms_return); 10303 False, atoms_return);
10300 10304
10301 for (i = 0; i < atom_count; i++) 10305 for (i = 0; i < atom_count; i++)
10302 *atom_refs[i].atom = atoms_return[i]; 10306 *(Atom *) ((char *) dpyinfo + atom_refs[i].offset) = atoms_return[i];
10303 10307
10304 /* Manual copy of last atom */ 10308 /* Manual copy of last atom */
10305 dpyinfo->Xatom_xsettings_sel = atoms_return[i]; 10309 dpyinfo->Xatom_xsettings_sel = atoms_return[i];
diff --git a/src/xterm.h b/src/xterm.h
index 4a5ebc66370..5415a77cf58 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -38,8 +38,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
38#include <X11/CoreP.h> /* foul, but we need this to use our own 38#include <X11/CoreP.h> /* foul, but we need this to use our own
39 window inside a widget instead of one 39 window inside a widget instead of one
40 that Xt creates... */ 40 that Xt creates... */
41#include <X11/StringDefs.h>
42
43typedef Widget xt_or_gtk_widget; 41typedef Widget xt_or_gtk_widget;
44#endif 42#endif
45 43