diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 308 | ||||
| -rw-r--r-- | src/alloc.c | 2 | ||||
| -rw-r--r-- | src/atimer.c | 2 | ||||
| -rw-r--r-- | src/buffer.c | 5 | ||||
| -rw-r--r-- | src/bytecode.c | 7 | ||||
| -rw-r--r-- | src/callproc.c | 115 | ||||
| -rw-r--r-- | src/dbusbind.c | 8 | ||||
| -rw-r--r-- | src/dired.c | 2 | ||||
| -rw-r--r-- | src/dispextern.h | 7 | ||||
| -rw-r--r-- | src/dispnew.c | 6 | ||||
| -rw-r--r-- | src/emacs.c | 89 | ||||
| -rw-r--r-- | src/eval.c | 71 | ||||
| -rw-r--r-- | src/fileio.c | 139 | ||||
| -rw-r--r-- | src/filelock.c | 20 | ||||
| -rw-r--r-- | src/fns.c | 26 | ||||
| -rw-r--r-- | src/frame.c | 2 | ||||
| -rw-r--r-- | src/gnutls.h | 2 | ||||
| -rw-r--r-- | src/image.c | 10 | ||||
| -rw-r--r-- | src/inotify.c | 33 | ||||
| -rw-r--r-- | src/keyboard.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 25 | ||||
| -rw-r--r-- | src/lread.c | 96 | ||||
| -rw-r--r-- | src/makefile.w32-in | 2 | ||||
| -rw-r--r-- | src/nsfns.m | 6 | ||||
| -rw-r--r-- | src/nsmenu.m | 6 | ||||
| -rw-r--r-- | src/nsterm.m | 16 | ||||
| -rw-r--r-- | src/print.c | 13 | ||||
| -rw-r--r-- | src/process.c | 157 | ||||
| -rw-r--r-- | src/process.h | 8 | ||||
| -rw-r--r-- | src/profiler.c | 12 | ||||
| -rw-r--r-- | src/regex.c | 33 | ||||
| -rw-r--r-- | src/regex.h | 46 | ||||
| -rw-r--r-- | src/search.c | 2 | ||||
| -rw-r--r-- | src/sheap.c | 4 | ||||
| -rw-r--r-- | src/sound.c | 2 | ||||
| -rw-r--r-- | src/syntax.c | 272 | ||||
| -rw-r--r-- | src/syntax.h | 296 | ||||
| -rw-r--r-- | src/sysdep.c | 235 | ||||
| -rw-r--r-- | src/systime.h | 23 | ||||
| -rw-r--r-- | src/term.c | 51 | ||||
| -rw-r--r-- | src/termcap.c | 108 | ||||
| -rw-r--r-- | src/termhooks.h | 2 | ||||
| -rw-r--r-- | src/terminal.c | 4 | ||||
| -rw-r--r-- | src/undo.c | 7 | ||||
| -rw-r--r-- | src/unexaix.c | 19 | ||||
| -rw-r--r-- | src/unexcoff.c | 15 | ||||
| -rw-r--r-- | src/unexcw.c | 4 | ||||
| -rw-r--r-- | src/unexelf.c | 6 | ||||
| -rw-r--r-- | src/unexhp9k800.c | 4 | ||||
| -rw-r--r-- | src/unexmacosx.c | 4 | ||||
| -rw-r--r-- | src/w32.c | 15 | ||||
| -rw-r--r-- | src/w32.h | 2 | ||||
| -rw-r--r-- | src/xdisp.c | 3 | ||||
| -rw-r--r-- | src/xrdb.c | 5 | ||||
| -rw-r--r-- | src/xsettings.c | 6 | ||||
| -rw-r--r-- | src/xterm.c | 125 |
56 files changed, 1453 insertions, 1037 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index b95488c1e70..60e7e376729 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,309 @@ +2013-07-13 Paul Eggert <eggert@cs.ucla.edu> + + Don't lose top specpdl entry when memory is exhausted. + * eval.c (grow_specpdl): Increment specpdl top by 1 and check for + specpdl overflow here, to simplify callers; all callers changed. + Always reserve an unused entry at the stack top; this avoids + losing the top entry's information when memory is exhausted. + +2013-07-12 Paul Eggert <eggert@cs.ucla.edu> + + Clean up errno reporting and fix some errno-reporting bugs. + * callproc.c (Fcall_process): + * fileio.c (Fcopy_file, Finsert_file_contents, Fwrite_region): + * process.c (create_process, Fmake_network_process): + * unexaix.c (report_error): + * unexcoff.c (report_error): + Be more careful about reporting the errno of failed operations. + The code previously reported the wrong errno sometimes. + Also, prefer report_file_errno to setting errno + report_file_error. + (Fcall_process): Look at openp return value rather than at path, + as that's a bit faster and clearer when there's a numeric predicate. + * fileio.c (report_file_errno): New function, with most of the + old contents of report_file_error. + (report_file_error): Use it. + (Ffile_exists_p, Ffile_accessible_directory_p): + Set errno to 0 when it is junk. + * fileio.c (Faccess_file): + * image.c (x_create_bitmap_from_file): + Use faccessat rather than opening the file, to avoid the hassle of + having a file descriptor open. + * lisp.h (report_file_errno): New decl. + * lread.c (Flocate_file_internal): File descriptor 0 is valid, too. + + Minor EBADF fixes. + * process.c (create_process, wait_reading_process_output) [AIX]: + Remove obsolete SIGHUP-related code, as Emacs no longer disables + SIGHUP, so EBADF is no longer acceptable here (it wouldn't work in + a multithreaded environment anyway). + * sysdep.c (emacs_close): It's not dangerous to invoke emacs_close (-1). + +2013-07-12 Andreas Schwab <schwab@linux-m68k.org> + + * image.c (x_find_image_file): Don't close a remote file handle. + +2013-07-12 Paul Eggert <eggert@cs.ucla.edu> + + Fix races with threads and file descriptors. + * callproc.c (Fcall_process_region): + * dired.c (open_directory): + * emacs.c (main, Fdaemon_initialized): + * image.c (x_find_image_file): + * inotify.c (Finotify_rm_watch): + * lread.c (Flocate_file_internal): + * process.c (Fnetwork_interface_list, Fnetwork_interface_info): + * term.c (term_mouse_moveto, init_tty): + * termcap.c (tgetent): + * unexaix.c, unexcoff.c (report_error, report_error_1, adjust_lnnoptrs) + * unexaix.c, unexcoff.c, unexcw.c, unexelf.c (unexec): + * unexhp9k800.c, unexmacosx.c (unexec): + * callproc.c (Fcall_process_region): + Use emacs_close, not close. + * sysdep.c (POSIX_CLOSE_RESTART, posix_close) [!POSIX_CLOSE_RESTART]: + New macro and function, which emulates the POSIX_CLOSE_RESTART macro + and posix_close function on current platforms (which all lack them). + (emacs_close): Use it. This should fix the races on GNU/Linux and + on AIX and on future platforms that support POSIX_CLOSE_RESTART, + and it should avoid closing random victim file descriptors on + other platforms. + +2013-07-11 Paul Eggert <eggert@cs.ucla.edu> + + * inotify.c (uninitialized): Remove. All uses replaced by -1. + (Finotify_add_watch): Simplify, since -1 means uninitialized now. + Touch up doc a bit. + + * eval.c (backtrace_function, backtrace_args): Now EXTERNALLY_VISIBLE. + This is for .gdbinit xbacktrace. + + * sysdep.c, term.c, termcap.c, terminal.c: Integer-related minor fixes. + * sysdep.c (emacs_get_tty): Return void, since nobody uses the value. + (emacs_set_tty): Now static. + * sysdep.c (emacs_set_tty, tabs_safe_p, emacs_close): + * term.c (tty_capable_p, tty_default_color_capabilities) + (get_tty_terminal, term_mouse_movement) + (handle_one_term_event, init_tty, maybe_fatal): + * termcap.c (tgetst1, struct termcap_buffer, valid_filename_p) + (tgetent, scan_file, name_match, compare_contin): + * terminal.c (get_terminal): + Use bool for boolean. + * sysdep.c (init_system_name): Don't overflow stack on huge hostname. + Prefer char to unsigned char if either will do. + * term.c (OUTPUT, turn_on_face): Omit unnecessary casts to int. + (tty_write_glyphs): Prefer int to unsigned. + (produce_glyphless_glyph): Remove 2nd (unused) int arg. + All callers changed. + * termcap.c (tprint, main) [TEST]: Remove non-working test. + +2013-07-10 Paul Eggert <eggert@cs.ucla.edu> + + Port to C89. + * bytecode.c (BYTE_CODE_THREADED): Do not define if __STRICT_ANSI__. + (B__dummy__): New dummy symbol, to pacify C89. + * dbusbind.c (XD_DEBUG_MESSAGE): Omit debugging on C89 hosts, since + they can't grok varargs macros. + * dispnew.c (add_window_display_history) + (add_frame_display_history): + * print.c (print_object): + * xdisp.c (debug_method_add): + Use %p printf format only for void pointers. + * emacs.c (usage_message): New constant, replacing ... + (USAGE1, USAGE2, USAGE3): Remove; they were too long for C89. + (main): Adjust to usage reorg. + * fns.c (syms_of_fns): + * profiler.c (syms_of_profiler): + Don't use non-constant struct initializers. + * gnutls.h (gnutls_initstage_t): + * lisp.h (enum Lisp_Fwd_Type): + * lread.c (lisp_file_lexically_bound_p): + * xsettings.c (anonymous enum): + Remove trailing comma. + * xsettings.c (apply_xft_settings): Use %f, not %lf; %lf is a C99ism. + * lisp.h (ENUM_BF): Use unsigned if pedantic. + (DEFUN_FUNCTION_INIT): New macro, that falls back on a cast if pre-C99. + (DEFUN): Use it. + * regex.c (const_re_char): New type, to pacify strict C89. + All uses of 'const re_char' replaced to use it. + * regex.h (_Restrict_): Rename from __restrict, to avoid clash + with glibc when strict C89. This change is imported from gnulib. + All uses changed. + (_Restrict_arr_): Rename from __restrict_arr, similarly. + * sysdep.c (time_from_jiffies) [!HAVE_LONG_LONG_INT]: + Omit GNU_LINUX implementation, since it requires long long. + * xterm.c (x_draw_underwave): + Do not assume the traditional order of struct's members. + (x_term_init): Rewrite to avoid the need for non-constant structure + initializers. + + Syntax cleanup, mostly replacing macros with functions. +` This removes the need for the syntax_temp hack. + * search.c: Include syntax.h after buffer.h, since syntax.h uses BVAR. + * syntax.c (SYNTAX_INLINE): New macro. + (SYNTAX_FLAGS_COMSTART_FIRST, SYNTAX_FLAGS_COMSTART_SECOND) + (SYNTAX_FLAGS_COMEND_FIRST, SYNTAX_FLAGS_COMEND_SECOND) + (SYNTAX_FLAGS_PREFIX, SYNTAX_FLAGS_COMMENT_STYLEB) + (SYNTAX_FLAGS_COMMENT_STYLEC, SYNTAX_FLAGS_COMMENT_STYLEC2) + (SYNTAX_FLAGS_COMMENT_NESTED, SYNTAX_FLAGS_COMMENT_STYLE) + (SYNTAX_COMEND_FIRST): Now functions, not macros. + (ST_COMMENT_STYLE, ST_STRING_STYLE, INTERVALS_AT_ONCE): + Now constants, not macros. + (syntax_temp) [!__GNUC__]: Remove. + (SYNTAX_PREFIX): Remove; all uses replaced by syntax_prefix_flag_p. + (syntax_prefix_flag_p): Move implementation of SYNTAX_PREFIX here. + (SET_RAW_SYNTAX_ENTRY, SET_RAW_SYNTAX_ENTRY_RANGE, SYNTAX_MATCH) + (SETUP_SYNTAX_TABLE, SETUP_SYNTAX_TABLE_FOR_OBJECT): + Move here from syntax.h; now functions, not macros. Except for the + last function, these are static since only syntax.c uses them. + (syntax_multibyte): Rename from SYNTAX_WITH_MULTIBYTE_CHECK. + All uses changed. Now a function, not a macro; use this fact + to simplify the code. + (scan_lists, scan_sexps_forward): Remove workarounds for ancient + compiler bugs; no longer relevant. + * syntax.h: Use INLINE_HEADER_BEGIN, INLINE_HEADER_END. + (SYNTAX_INLINE): New macro. + (struct gl_state_s, gl_state): Move earlier, so that it's in scope + for the new functions. Use bool for boolean member. + (SYNTAX_ENTRY, SYNTAX, SYNTAX_WITH_FLAGS, SYNTAX_MATCH) + (SYNTAX_TABLE_BYTE_TO_CHAR, UPDATE_SYNTAX_TABLE_FORWARD) + (UPDATE_SYNTAX_TABLE_BACKWARD, UPDATE_SYNTAX_TABLE) + (SETUP_BUFFER_SYNTAX_TABLE): + Now extern inline functions, not macros. + (CURRENT_SYNTAX_TABLE, SYNTAX_ENTRY_INT): + Remove; all uses replaced by implementation. + (syntax_temp) [!__GNUC__]: Remove decl. + (SETUP_SYNTAX_TABLE_FOR_OBJECT): New decl. + +2013-07-10 Jan Djärv <jan.h.d@swipnet.se> + + * emacs.c (main): Fix syntax error. + +2013-07-10 Paul Eggert <eggert@cs.ucla.edu> + + Timestamp fixes for undo (Bug#14824). + * atimer.c (schedule_atimer): + * fileio.c (Ffile_newer_than_file_p): + Minor cleanup: use EMACS_TIME_LT so that we can remove EMACS_TIME_GT. + * buffer.c (buffer-undo-list): Document (t . 0) and (t . -1). + * fileio.c (Fclear_visited_file_modtime): Move to lisp/files.el. + (syms_of_fileio): Remove Sclear_visited_file_name. + (Fvisited_file_modtime): Return -1, not (-1 ...), when the visited + file doesn't exist; this avoids an ambiguity with negative timestamps. + (Fset_visited_file_modtime): Accept -1 and 0 as time-list arg. + * systime.h (make_emacs_time, invalid_emacs_time): + Don't assume struct timespec layout; POSIX doesn't guarantee it. + (EMACS_TIME_NE, EMACS_TIME_GT, EMACS_TIME_GE): Remove. + * undo.c (record_first_change): Push (visited-file-modtime) onto + undo list rather than reimplementing it by hand, incorrectly. + +2013-07-09 Ken Brown <kbrown@cornell.edu> + + * sheap.c (STATIC_HEAP_SIZE) [__x86_64__]: Increase to 18MB. + +2013-07-09 Juanma Barranquero <lekktu@gmail.com> + + * makefile.w32-in ($(BLD)/emacs.$(O), $(BLD)/sysdep.$(O)): Update. + +2013-07-09 Paul Eggert <eggert@cs.ucla.edu> + + Handle errno and exit status a bit more carefully. + * callproc.c (child_setup) [!DOS_NT]: Don't try to stuff an error + number into an exit status. Instead, use EXIT_CANCELED. + (child_setup) [!MSDOS]: Avoid possible deadlock with vfork. + * callproc.c (relocate_fd): + * emacs.c (close_output_streams, main): + * process.c (create_process): + * sysdep.c (sys_subshell) [!DOS_NT || !WINDOWSNT]: + Use emacs_perror for simplicity. + * callproc.c (relocate_fd, main): + * sysdep.c (sys_subshell): + Exit with EXIT_CANCELED etc., not 1, when exec setup fails. + (shut_down_emacs): Use emacs_write, not write. + * emacs.c, sysdep.c: Don't include <ignore-value.h>. + * fileio.c (Fcopy_file, e_write): + * nsterm.m (ns_select): + * process.c (send_process): + * sound.c (vox_write): + Use emacs_write_sig, not emacs_write. + * lisp.h (emacs_write_sig, emacs_perror): New decls. + * process.h (EXIT_CANCELED), EXIT_CANNOT_INVOKE, EXIT_ENOENT): + New constants. + * sysdep.c (emacs_backtrace): Use emacs_write, not ignore_value + of write. + (emacs_full_write): New function. + (emacs_write): Rewrite to use it. + (emacswrite_sig, emacs_perror): New functions. + * xrdb.c (fatal): Don't invoke perror, since errno might be garbage. + +2013-07-08 Magnus Henoch <magnus.henoch@gmail.com> (tiny change). + + * image.c (imagemagick_load_image): Do not use MagickExportImagePixels + on NS even if it is present. Pixmap on NS is a void*. + +2013-07-07 Paul Eggert <eggert@cs.ucla.edu> + + Port to Ubuntu 10 (Bug#14803). + Problem reported by T.V. Raman. + * process.c (close_on_exec, accept4, process_socket): + Define these if !HAVE_ACCEPT4, not if !SOCK_CLOEXEC. + +2013-07-07 Eli Zaretskii <eliz@gnu.org> + + * w32.c (sys_dup): Declare prototype. + + * filelock.c: + * emacs.c: + * callproc.c [WINDOWSNT]: Include sys/socket.h. + +2013-07-07 Paul Eggert <eggert@cs.ucla.edu> + + Make file descriptors close-on-exec when possible (Bug#14803). + This simplifies Emacs a bit, since it no longer needs to worry + about closing file descriptors by hand in some cases. + It also fixes some unlikely races. Not all such races, as + libraries often open files internally without setting + close-on-exec, but it's an improvement. + * alloc.c (valid_pointer_p) [!WINDOWSNT]: + * callproc.c (Fcall_process) [!MSDOS]: + * emacs.c (main) [!DOS_NT]: + * nsterm.m (ns_term_init): + * process.c (create_process): + Use 'pipe2' with O_CLOEXEC instead of 'pipe'. + * emacs.c (Fcall_process_region) [HAVE_MKOSTEMP]: + * filelock.c (create_lock_file) [HAVE_MKOSTEMP]: + Prefer mkostemp with O_CLOEXEC to mkstemp. + * callproc.c (relocate_fd) [!WINDOWSNT]: + * emacs.c (main): Use F_DUPFD_CLOEXEC, not plain F_DUPFD. + No need to use fcntl (..., F_SETFD, FD_CLOEXEC), since we're + now using pipe2. + * filelock.c (create_lock_file) [! HAVE_MKOSTEMP]: + Make the resulting file descriptor close-on-exec. + * lisp.h, lread.c, process.c (close_load_descs, close_process_descs): + * lread.c (load_descriptor_list, load_descriptor_unwind): + Remove; no longer needed. All uses removed. + * process.c (SOCK_CLOEXEC): Define to 0 if not supplied by system. + (close_on_exec, accept4, process_socket) [!SOCK_CLOEXEC]: + New functions. + (socket) [!SOCK_CLOEXEC]: Supply a substitute. + (Fmake_network_process, Fnetwork_interface_list): + (Fnetwork_interface_info, server_accept_connection): + Make newly-created socket close-on-exec. + * sysdep.c (emacs_open, emacs_fopen): + Make new-created descriptor close-on-exec. + * w32.c (fcntl): Support F_DUPFD_CLOEXEC well enough for Emacs. + * w32.c, w32.h (pipe2): Rename from 'pipe', with new flags arg. + +2013-07-07 Jan Djärv <jan.h.d@swipnet.se> + + * nsterm.m (sendEvent:): Propagate keyboard events to modal windows + for NS_IMPL_GNUSTEP. + +2013-07-07 Paul Eggert <eggert@cs.ucla.edu> + + Fix openp errno handling. + * callproc.c (Fcall_process): Preserve openp errno around close. + * lread.c (openp): Set errno when returning -1, as some callers + expect this. + 2013-07-06 Jan Djärv <jan.h.d@swipnet.se> * nsterm.m (sendEvent:): Handle NSAPP_DATA2_RUNFILEDIALOG. @@ -655,7 +961,7 @@ (VALMASK): Also a constant, for benefit of old GDB. (LISP_INT_TAG_P): Remove; no longer needed as the only caller is INTEGERP, which can fold it in. - (XLI, XIL, XHASH, XTYPE,XINT, XFASTINT, XUINT) + (XLI, XIL, XHASH, XTYPE, XINT, XFASTINT, XUINT) (make_number, XPNTR, XUNTAG, EQ, XCONS, XVECTOR, XSTRING, XSYMBOL) (XFLOAT, XPROCESS, XWINDOW, XTERMINAL, XSUBR, XBUFFER, XCHAR_TABLE) (XSUB_CHAR_TABLE, XBOOL_VECTOR, make_lisp_ptr, CHECK_TYPE) diff --git a/src/alloc.c b/src/alloc.c index 230b3b614d7..6ef6af1e3a1 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -4750,7 +4750,7 @@ valid_pointer_p (void *p) Unfortunately, we cannot use NULL_DEVICE here, as emacs_write may not validate p in that case. */ - if (pipe (fd) == 0) + if (pipe2 (fd, O_CLOEXEC) == 0) { bool valid = emacs_write (fd[1], (char *) p, 16) == 16; 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) struct atimer *a = atimers, *prev = NULL; /* Look for the first atimer that is ripe after T. */ - while (a && EMACS_TIME_GT (t->expiration, a->expiration)) + while (a && EMACS_TIME_LT (a->expiration, t->expiration)) prev = a, a = a->next; /* Insert T in front of the atimer found, if any. */ diff --git a/src/buffer.c b/src/buffer.c index 2555b5c17ac..19e3982a8a4 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -6096,6 +6096,11 @@ and is the visited file's modification time, as of that time. If the modification time of the most recent save is different, this entry is obsolete. +An entry (t . 0) means means the buffer was previously unmodified but +its time stamp was unknown because it was not associated with a file. +An entry (t . -1) is similar, except that it means the buffer's visited +file did not exist. + An entry (nil PROPERTY VALUE BEG . END) indicates that a text property was modified between BEG and END. PROPERTY is the property name, and VALUE is the old value. diff --git a/src/bytecode.c b/src/bytecode.c index a22be984b44..f186f7d1bc3 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -59,7 +59,8 @@ by Hallvard: indirect threaded, using GCC's computed goto extension. This code, as currently implemented, is incompatible with BYTE_CODE_SAFE and BYTE_CODE_METER. */ -#if defined (__GNUC__) && !defined (BYTE_CODE_SAFE) && !defined (BYTE_CODE_METER) +#if (defined __GNUC__ && !defined __STRICT_ANSI__ \ + && !defined BYTE_CODE_SAFE && !defined BYTE_CODE_METER) #define BYTE_CODE_THREADED #endif @@ -285,8 +286,10 @@ enum byte_code_op #ifdef BYTE_CODE_SAFE Bscan_buffer = 0153, /* No longer generated as of v18. */ - Bset_mark = 0163 /* this loser is no longer generated as of v18 */ + Bset_mark = 0163, /* this loser is no longer generated as of v18 */ #endif + + B__dummy__ = 0 /* Pacify C89. */ }; /* Whether to maintain a `top' and `bottom' field in the stack frame. */ diff --git a/src/callproc.c b/src/callproc.c index 6de8113dc14..30f9dc58d46 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/>. */ #ifdef WINDOWSNT #define NOMINMAX +#include <sys/socket.h> /* for fcntl */ #include <windows.h> #include "w32.h" #define _P_NOWAIT 1 /* from process.h */ @@ -418,9 +419,10 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * default_output_mode); if (fd_output < 0) { + int open_errno = errno; output_file = DECODE_FILE (output_file); - report_file_error ("Opening process output file", - Fcons (output_file, Qnil)); + report_file_errno ("Opening process output file", + Fcons (output_file, Qnil), open_errno); } if (STRINGP (error_file) || NILP (error_file)) output_to_buffer = 0; @@ -429,16 +431,19 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * /* Search for program; barf if not found. */ { struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; + int ok; GCPRO4 (infile, buffer, current_dir, error_file); - openp (Vexec_path, args[0], Vexec_suffixes, &path, make_number (X_OK)); + ok = openp (Vexec_path, args[0], Vexec_suffixes, &path, make_number (X_OK)); UNGCPRO; + if (ok < 0) + { + int openp_errno = errno; + emacs_close (filefd); + report_file_errno ("Searching for program", + Fcons (args[0], Qnil), openp_errno); + } } - if (NILP (path)) - { - emacs_close (filefd); - report_file_error ("Searching for program", Fcons (args[0], Qnil)); - } /* If program file name starts with /: for quoting a magic name, discard that. */ @@ -496,11 +501,13 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * mktemp (tempfile); outfilefd = emacs_open (tempfile, O_WRONLY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); - if (outfilefd < 0) { - emacs_close (filefd); - report_file_error ("Opening process output file", - Fcons (build_string (tempfile), Qnil)); - } + if (outfilefd < 0) + { + int open_errno = errno; + emacs_close (filefd); + report_file_errno ("Opening process output file", + Fcons (build_string (tempfile), Qnil), open_errno); + } } else outfilefd = fd_output; @@ -517,12 +524,11 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * { #ifndef MSDOS int fd[2]; - if (pipe (fd) == -1) + if (pipe2 (fd, O_CLOEXEC) != 0) { int pipe_errno = errno; emacs_close (filefd); - errno = pipe_errno; - report_file_error ("Creating process pipe", Qnil); + report_file_errno ("Creating process pipe", Qnil, pipe_errno); } fd0 = fd[0]; fd1 = fd[1]; @@ -544,6 +550,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * if (fd_error < 0) { + int open_errno = errno; emacs_close (filefd); if (fd0 != filefd) emacs_close (fd0); @@ -556,7 +563,8 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * error_file = build_string (NULL_DEVICE); else if (STRINGP (error_file)) error_file = DECODE_FILE (error_file); - report_file_error ("Cannot redirect stderr", Fcons (error_file, Qnil)); + report_file_errno ("Cannot redirect stderr", + Fcons (error_file, Qnil), open_errno); } #ifdef MSDOS /* MW, July 1993 */ @@ -584,10 +592,12 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * fd0 = emacs_open (tempfile, O_RDONLY | O_BINARY, 0); if (fd0 < 0) { + int open_errno = errno; unlink (tempfile); emacs_close (filefd); - report_file_error ("Cannot re-open temporary file", - Fcons (build_string (tempfile), Qnil)); + report_file_errno ("Cannot re-open temporary file", + Fcons (build_string (tempfile), Qnil), + open_errno); } } else @@ -705,10 +715,7 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) * } if (pid < 0) - { - errno = child_errno; - report_file_error ("Doing vfork", Qnil); - } + report_file_errno ("Doing vfork", Qnil, child_errno); if (INTEGERP (buffer)) return unbind_to (count, Qnil); @@ -1034,29 +1041,29 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1); coding_systems = Qt; -#ifdef HAVE_MKSTEMP +#if defined HAVE_MKOSTEMP || defined HAVE_MKSTEMP { - int fd; + int fd, open_errno; block_input (); +# ifdef HAVE_MKOSTEMP + fd = mkostemp (tempfile, O_CLOEXEC); +# else fd = mkstemp (tempfile); +# endif + open_errno = errno; unblock_input (); - if (fd == -1) - report_file_error ("Failed to open temporary file", - Fcons (build_string (tempfile), Qnil)); - else - close (fd); + if (fd < 0) + report_file_errno ("Failed to open temporary file", + Fcons (build_string (tempfile), Qnil), open_errno); + emacs_close (fd); } #else - errno = 0; + errno = EEXIST; mktemp (tempfile); if (!*tempfile) - { - if (!errno) - errno = EEXIST; - report_file_error ("Failed to open temporary file using pattern", - Fcons (pattern, Qnil)); - } + report_file_error ("Failed to open temporary file using pattern", + Fcons (pattern, Qnil)); #endif filename_string = build_string (tempfile); @@ -1182,15 +1189,6 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, pid_t pid = getpid (); - /* Close Emacs's descriptors that this process should not have. */ - close_process_descs (); - - /* DOS_NT isn't in a vfork, so if we are in the middle of load-file, - we will lose if we call close_load_descs here. */ -#ifndef DOS_NT - close_load_descs (); -#endif - /* Note that use of alloca is always safe here. It's obvious for systems that do not have true vfork or that have true (stack) alloca. If using vfork and C_ALLOCA (when Emacs used to include @@ -1223,7 +1221,7 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, are changed between the check and this chdir, but we should at least check. */ if (chdir (temp) < 0) - _exit (errno); + _exit (EXIT_CANCELED); #else /* DOS_NT */ /* Get past the drive letter, so that d:/ is left alone. */ if (i > 2 && IS_DEVICE_SEP (temp[1]) && IS_DIRECTORY_SEP (temp[2])) @@ -1352,9 +1350,11 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, emacs_close (1); emacs_close (2); + /* Redirect file descriptors and clear FD_CLOEXEC on the redirected ones. */ dup2 (in, 0); dup2 (out, 1); dup2 (err, 2); + emacs_close (in); if (out != in) emacs_close (out); @@ -1366,10 +1366,12 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp, execve (new_argv[0], new_argv, env); - emacs_write (1, "Can't exec program: ", 20); - emacs_write (1, new_argv[0], strlen (new_argv[0])); - emacs_write (1, "\n", 1); - _exit (1); + /* Don't output the program name here, as it can be arbitrarily long, + and a long write from a vforked child to its parent can cause a + deadlock. */ + emacs_perror ("child process"); + + _exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE); #else /* MSDOS */ pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env); @@ -1392,16 +1394,11 @@ relocate_fd (int fd, int minfd) return fd; else { - int new = fcntl (fd, F_DUPFD, minfd); + int new = fcntl (fd, F_DUPFD_CLOEXEC, minfd); if (new == -1) { - const char *message_1 = "Error while setting up child: "; - const char *errmessage = strerror (errno); - const char *message_2 = "\n"; - emacs_write (2, message_1, strlen (message_1)); - emacs_write (2, errmessage, strlen (errmessage)); - emacs_write (2, message_2, strlen (message_2)); - _exit (1); + emacs_perror ("while setting up child"); + _exit (EXIT_CANCELED); } emacs_close (fd); return new; 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; } while (0) #else /* !DBUS_DEBUG */ -#define XD_DEBUG_MESSAGE(...) \ +# if __STDC_VERSION__ < 199901 +# define XD_DEBUG_MESSAGE (void) /* Pre-C99 compilers cannot debug. */ +# else +# define XD_DEBUG_MESSAGE(...) \ do { \ if (!NILP (Vdbus_debug)) \ { \ @@ -151,7 +154,8 @@ static bool xd_in_read_queued_messages = 0; message ("%s: %s", __func__, s); \ } \ } while (0) -#define XD_DEBUG_VALID_LISP_OBJECT_P(object) +# endif +# define XD_DEBUG_VALID_LISP_OBJECT_P(object) #endif /* Check whether TYPE is a basic DBusType. */ 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) d = fdopendir (fd); opendir_errno = errno; if (! d) - close (fd); + emacs_close (fd); } #endif diff --git a/src/dispextern.h b/src/dispextern.h index 1dd96c6638d..e0d04231d3a 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3298,7 +3298,7 @@ int image_ascent (struct image *, struct face *, struct glyph_slice *); void get_tty_size (int, int *, int *); void request_sigio (void); void unrequest_sigio (void); -int tabs_safe_p (int); +bool tabs_safe_p (int); void init_baud_rate (int); void init_sigio (int); void ignore_sigio (void); @@ -3470,11 +3470,12 @@ extern int string_cost (const char *); extern int per_line_cost (const char *); extern void calculate_costs (struct frame *); extern void produce_glyphs (struct it *); -extern int tty_capable_p (struct tty_display_info *, unsigned, unsigned long, unsigned long); +extern bool tty_capable_p (struct tty_display_info *, unsigned, + unsigned long, unsigned long); extern void set_tty_color_mode (struct tty_display_info *, struct frame *); extern struct terminal *get_named_tty (const char *); extern void create_tty_output (struct frame *); -extern struct terminal *init_tty (const char *, const char *, int); +extern struct terminal *init_tty (const char *, const char *, bool); extern void tty_append_glyph (struct it *); diff --git a/src/dispnew.c b/src/dispnew.c index 31b8a1310ea..1eb097f05ab 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -213,6 +213,7 @@ static void add_window_display_history (struct window *w, const char *msg, bool paused_p) { char *buf; + void *ptr = w; if (history_idx >= REDISPLAY_HISTORY_SIZE) history_idx = 0; @@ -222,7 +223,7 @@ add_window_display_history (struct window *w, const char *msg, bool paused_p) snprintf (buf, sizeof redisplay_history[0].trace, "%"pMu": window %p (`%s')%s\n%s", history_tick++, - w, + ptr, ((BUFFERP (w->contents) && STRINGP (BVAR (XBUFFER (w->contents), name))) ? SSDATA (BVAR (XBUFFER (w->contents), name)) @@ -240,6 +241,7 @@ static void add_frame_display_history (struct frame *f, bool paused_p) { char *buf; + void *ptr = f; if (history_idx >= REDISPLAY_HISTORY_SIZE) history_idx = 0; @@ -248,7 +250,7 @@ add_frame_display_history (struct frame *f, bool paused_p) sprintf (buf, "%"pMu": update frame %p%s", history_tick++, - f, paused_p ? " ***paused***" : ""); + ptr, paused_p ? " ***paused***" : ""); } diff --git a/src/emacs.c b/src/emacs.c index ec17322f57a..274321482e1 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/>. */ #include <unistd.h> #include <close-stream.h> -#include <ignore-value.h> #include "lisp.h" #ifdef WINDOWSNT #include <fcntl.h> +#include <sys/socket.h> #include "w32.h" #include "w32heap.h" #endif @@ -197,10 +197,10 @@ int initial_argc; static void sort_args (int argc, char **argv); static void syms_of_emacs (void); -/* MSVC needs each string be shorter than 2048 bytes, so the usage +/* C89 needs each string be at most 509 characters, so the usage strings below are split to not overflow this limit. */ -#define USAGE1 "\ -Usage: %s [OPTION-OR-FILENAME]...\n\ +static char const *const usage_message[] = + { "\ \n\ Run Emacs, the extensible, customizable, self-documenting real-time\n\ display editor. The recommended way to start Emacs for normal editing\n\ @@ -211,11 +211,15 @@ read the main documentation for these command-line arguments.\n\ \n\ Initialization options:\n\ \n\ +", + "\ --batch do not do interactive display; implies -q\n\ --chdir DIR change to directory DIR\n\ --daemon start a server in the background\n\ --debug-init enable Emacs Lisp debugger for init file\n\ --display, -d DISPLAY use X server DISPLAY\n\ +", + "\ --no-desktop do not load a saved desktop\n\ --no-init-file, -q load neither ~/.emacs nor default.el\n\ --no-shared-memory, -nl do not use shared memory\n\ @@ -223,14 +227,16 @@ Initialization options:\n\ --no-site-lisp, -nsl do not add site-lisp directories to load-path\n\ --no-splash do not display a splash screen on startup\n\ --no-window-system, -nw do not communicate with X, ignoring $DISPLAY\n\ +", + "\ --quick, -Q equivalent to:\n\ -q --no-site-file --no-site-lisp --no-splash\n\ --script FILE run FILE as an Emacs Lisp script\n\ --terminal, -t DEVICE use DEVICE for terminal I/O\n\ --user, -u USER load ~USER/.emacs instead of your own\n\ -\n%s" - -#define USAGE2 "\ +\n\ +", + "\ Action options:\n\ \n\ FILE visit FILE using find-file\n\ @@ -239,6 +245,8 @@ FILE visit FILE using find-file\n\ --directory, -L DIR add DIR to variable load-path\n\ --eval EXPR evaluate Emacs Lisp expression EXPR\n\ --execute EXPR evaluate Emacs Lisp expression EXPR\n\ +", + "\ --file FILE visit FILE using find-file\n\ --find-file FILE visit FILE using find-file\n\ --funcall, -f FUNC call Emacs Lisp function FUNC with no arguments\n\ @@ -246,9 +254,9 @@ FILE visit FILE using find-file\n\ --kill exit without asking for confirmation\n\ --load, -l FILE load Emacs Lisp FILE using the load function\n\ --visit FILE visit FILE using find-file\n\ -\n" - -#define USAGE3 "\ +\n\ +", + "\ Display options:\n\ \n\ --background-color, -bg COLOR window background color\n\ @@ -256,6 +264,8 @@ Display options:\n\ used for debugging Emacs\n\ --border-color, -bd COLOR main border color\n\ --border-width, -bw WIDTH width of main border\n\ +", + "\ --color, --color=MODE override color mode for character terminals;\n\ MODE defaults to `auto', and\n\ can also be `never', `always',\n\ @@ -263,17 +273,23 @@ Display options:\n\ --cursor-color, -cr COLOR color of the Emacs cursor indicating point\n\ --font, -fn FONT default font; must be fixed-width\n\ --foreground-color, -fg COLOR window foreground color\n\ +", + "\ --fullheight, -fh make the first frame high as the screen\n\ --fullscreen, -fs make the first frame fullscreen\n\ --fullwidth, -fw make the first frame wide as the screen\n\ --maximized, -mm make the first frame maximized\n\ --geometry, -g GEOMETRY window geometry\n\ +", + "\ --no-bitmap-icon, -nbi do not use picture of gnu for Emacs icon\n\ --iconic start Emacs in iconified state\n\ --internal-border, -ib WIDTH width between text and main border\n\ --line-spacing, -lsp PIXELS additional space to put between lines\n\ --mouse-color, -ms COLOR mouse cursor color in Emacs window\n\ --name NAME title for initial Emacs frame\n\ +", + "\ --no-blinking-cursor, -nbc disable blinking cursor\n\ --reverse-video, -r, -rv switch foreground and background\n\ --title, -T TITLE title for initial Emacs frame\n\ @@ -282,9 +298,9 @@ Display options:\n\ --parent-id XID set parent window\n\ --help display this help and exit\n\ --version output version information and exit\n\ -\n" - -#define USAGE4 "\ +\n\ +", + "\ You can generally also specify long option names with a single -; for\n\ example, -batch as well as --batch. You can use any unambiguous\n\ abbreviation for a --option.\n\ @@ -294,6 +310,7 @@ Emacs' operation. See the main documentation.\n\ \n\ Report bugs to bug-gnu-emacs@gnu.org. First, please see the Bugs\n\ section of the Emacs manual or the file BUGS.\n" + }; /* True if handling a fatal error already. */ @@ -641,9 +658,7 @@ close_output_streams (void) { if (close_stream (stdout) != 0) { - fprintf (stderr, "Write error to standard output: %s\n", - strerror (errno)); - fflush (stderr); + emacs_perror ("Write error to standard output"); _exit (EXIT_FAILURE); } @@ -780,7 +795,7 @@ main (int argc, char **argv) execvp (argv[0], argv); /* If the exec fails, try to dump anyway. */ - perror ("execvp"); + emacs_perror (argv[0]); } #endif /* HAVE_PERSONALITY_LINUX32 */ @@ -878,7 +893,7 @@ main (int argc, char **argv) emacs_close (0); emacs_close (1); result = emacs_open (term, O_RDWR, 0); - if (result < 0 || dup (0) < 0) + if (result < 0 || fcntl (0, F_DUPFD_CLOEXEC, 1) < 0) { char *errstring = strerror (errno); fprintf (stderr, "%s: %s: %s\n", argv[0], term, errstring); @@ -925,9 +940,10 @@ main (int argc, char **argv) /* Handle the --help option, which gives a usage message. */ if (argmatch (argv, argc, "-help", "--help", 3, NULL, &skip_args)) { - printf (USAGE1, argv[0], USAGE2); - printf (USAGE3); - printf (USAGE4); + int i; + printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]); + for (i = 0; i < sizeof usage_message / sizeof *usage_message; i++) + fputs (usage_message[i], stdout); exit (0); } @@ -958,7 +974,7 @@ main (int argc, char **argv) use a pipe for synchronization. The parent waits for the child to close its end of the pipe (using `daemon-initialized') before exiting. */ - if (pipe (daemon_pipe) == -1) + if (pipe2 (daemon_pipe, O_CLOEXEC) != 0) { fprintf (stderr, "Cannot pipe!\n"); exit (1); @@ -983,7 +999,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem char buf[1]; /* Close unused writing end of the pipe. */ - close (daemon_pipe[1]); + emacs_close (daemon_pipe[1]); /* Just wait for the child to close its end of the pipe. */ do @@ -1003,13 +1019,13 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem exit (1); } - close (daemon_pipe[0]); + emacs_close (daemon_pipe[0]); exit (0); } if (f < 0) { - fprintf (stderr, "Cannot fork!\n"); - exit (1); + emacs_perror ("fork"); + exit (EXIT_CANCELED); } #ifdef DAEMON_MUST_EXEC @@ -1026,14 +1042,14 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr)) { fprintf (stderr, "daemon: child name too long\n"); - exit (1); + exit (EXIT_CANNOT_INVOKE); } argv[skip_args] = fdStr; execvp (argv[0], argv); - fprintf (stderr, "emacs daemon: exec failed: %d\n", errno); - exit (1); + emacs_perror (argv[0]); + exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE); } /* In exec'd: parse special dname into pipe and name info. */ @@ -1041,7 +1057,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem || strlen (dname_arg) < 1 || strlen (dname_arg) > 70) { fprintf (stderr, "emacs daemon: daemon name absent or too long\n"); - exit (1); + exit (EXIT_CANNOT_INVOKE); } dname_arg2[0] = '\0'; sscanf (dname_arg, "\n%d,%d\n%s", &(daemon_pipe[0]), &(daemon_pipe[1]), @@ -1053,10 +1069,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem if (dname_arg) daemon_name = xstrdup (dname_arg); /* Close unused reading end of the pipe. */ - close (daemon_pipe[0]); - /* Make sure that the used end of the pipe is closed on exec, so - that it is not accessible to programs started from .emacs. */ - fcntl (daemon_pipe[1], F_SETFD, FD_CLOEXEC); + emacs_close (daemon_pipe[0]); setsid (); #else /* DOS_NT */ @@ -1910,8 +1923,8 @@ shut_down_emacs (int sig, Lisp_Object stuff) char buf[sizeof format - 2 + INT_STRLEN_BOUND (int)]; int buflen = sprintf (buf, format, sig); char const *sig_desc = safe_strsignal (sig); - ignore_value (write (STDERR_FILENO, buf, buflen)); - ignore_value (write (STDERR_FILENO, sig_desc, strlen (sig_desc))); + emacs_write (STDERR_FILENO, buf, buflen); + emacs_write (STDERR_FILENO, sig_desc, strlen (sig_desc)); } } } @@ -2233,7 +2246,7 @@ from the parent process and its tty file descriptors. */) err |= dup2 (nfd, 0) < 0; err |= dup2 (nfd, 1) < 0; err |= dup2 (nfd, 2) < 0; - err |= close (nfd) != 0; + err |= emacs_close (nfd) != 0; /* Closing the pipe will notify the parent that it can exit. FIXME: In case some other process inherited the pipe, closing it here @@ -2243,7 +2256,7 @@ from the parent process and its tty file descriptors. */) call-process to make sure the pipe is never inherited by subprocesses. */ err |= write (daemon_pipe[1], "\n", 1) < 0; - err |= close (daemon_pipe[1]) != 0; + err |= emacs_close (daemon_pipe[1]) != 0; /* Set it to an invalid value so we know we've already run this function. */ daemon_pipe[1] = -1; diff --git a/src/eval.c b/src/eval.c index 451a7b0cc28..97e812dd890 100644 --- a/src/eval.c +++ b/src/eval.c @@ -114,6 +114,13 @@ Lisp_Object Vsignaling_function; frame is half-initialized. */ Lisp_Object inhibit_lisp_code; +/* These would ordinarily be static, but they need to be visible to GDB. */ +bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE; +Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE; +Lisp_Object backtrace_function (union specbinding *) EXTERNALLY_VISIBLE; +union specbinding *backtrace_next (union specbinding *) EXTERNALLY_VISIBLE; +union specbinding *backtrace_top (void) EXTERNALLY_VISIBLE; + static Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *); static Lisp_Object apply_lambda (Lisp_Object fun, Lisp_Object args); @@ -159,7 +166,7 @@ specpdl_func (union specbinding *pdl) return pdl->unwind.func; } -static Lisp_Object +Lisp_Object backtrace_function (union specbinding *pdl) { eassert (pdl->kind == SPECPDL_BACKTRACE); @@ -173,7 +180,7 @@ backtrace_nargs (union specbinding *pdl) return pdl->bt.nargs; } -static Lisp_Object * +Lisp_Object * backtrace_args (union specbinding *pdl) { eassert (pdl->kind == SPECPDL_BACKTRACE); @@ -212,10 +219,6 @@ set_backtrace_debug_on_exit (union specbinding *pdl, bool doe) /* Helper functions to scan the backtrace. */ -bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE; -union specbinding *backtrace_top (void) EXTERNALLY_VISIBLE; -union specbinding *backtrace_next (union specbinding *pdl) EXTERNALLY_VISIBLE; - bool backtrace_p (union specbinding *pdl) { return pdl >= specpdl; } @@ -2013,38 +2016,52 @@ If LEXICAL is t, evaluate using lexical scoping. */) return unbind_to (count, eval_sub (form)); } +/* Grow the specpdl stack by one entry. + The caller should have already initialized the entry. + Signal an error on stack overflow. + + Make sure that there is always one unused entry past the top of the + stack, so that the just-initialized entry is safely unwound if + memory exhausted and an error is signaled here. Also, allocate a + never-used entry just before the bottom of the stack; sometimes its + address is taken. */ + static void grow_specpdl (void) { - ptrdiff_t count = SPECPDL_INDEX (); - ptrdiff_t max_size = min (max_specpdl_size, PTRDIFF_MAX - 1000); - union specbinding *pdlvec = specpdl - 1; - ptrdiff_t pdlvecsize = specpdl_size + 1; - if (max_size <= specpdl_size) + specpdl_ptr++; + + if (specpdl_ptr == specpdl + specpdl_size) { - if (max_specpdl_size < 400) - max_size = max_specpdl_size = 400; + ptrdiff_t count = SPECPDL_INDEX (); + ptrdiff_t max_size = min (max_specpdl_size, PTRDIFF_MAX - 1000); + union specbinding *pdlvec = specpdl - 1; + ptrdiff_t pdlvecsize = specpdl_size + 1; if (max_size <= specpdl_size) - signal_error ("Variable binding depth exceeds max-specpdl-size", Qnil); + { + if (max_specpdl_size < 400) + max_size = max_specpdl_size = 400; + if (max_size <= specpdl_size) + signal_error ("Variable binding depth exceeds max-specpdl-size", + Qnil); + } + pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl); + specpdl = pdlvec + 1; + specpdl_size = pdlvecsize - 1; + specpdl_ptr = specpdl + count; } - pdlvec = xpalloc (pdlvec, &pdlvecsize, 1, max_size + 1, sizeof *specpdl); - specpdl = pdlvec + 1; - specpdl_size = pdlvecsize - 1; - specpdl_ptr = specpdl + count; } void record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs) { eassert (nargs >= UNEVALLED); - if (specpdl_ptr == specpdl + specpdl_size) - grow_specpdl (); specpdl_ptr->bt.kind = SPECPDL_BACKTRACE; specpdl_ptr->bt.debug_on_exit = false; specpdl_ptr->bt.function = function; specpdl_ptr->bt.args = args; specpdl_ptr->bt.nargs = nargs; - specpdl_ptr++; + grow_specpdl (); } /* Eval a sub-expression of the current expression (i.e. in the same @@ -3176,8 +3193,6 @@ specbind (Lisp_Object symbol, Lisp_Object value) CHECK_SYMBOL (symbol); sym = XSYMBOL (symbol); - if (specpdl_ptr == specpdl + specpdl_size) - grow_specpdl (); start: switch (sym->redirect) @@ -3191,7 +3206,7 @@ specbind (Lisp_Object symbol, Lisp_Object value) specpdl_ptr->let.symbol = symbol; specpdl_ptr->let.old_value = SYMBOL_VAL (sym); specpdl_ptr->let.saved_value = Qnil; - ++specpdl_ptr; + grow_specpdl (); do_specbind (sym, specpdl_ptr - 1, value); break; case SYMBOL_LOCALIZED: @@ -3224,7 +3239,7 @@ specbind (Lisp_Object symbol, Lisp_Object value) if (NILP (Flocal_variable_p (symbol, Qnil))) { specpdl_ptr->let.kind = SPECPDL_LET_DEFAULT; - ++specpdl_ptr; + grow_specpdl (); do_specbind (sym, specpdl_ptr - 1, value); return; } @@ -3232,7 +3247,7 @@ specbind (Lisp_Object symbol, Lisp_Object value) else specpdl_ptr->let.kind = SPECPDL_LET; - specpdl_ptr++; + grow_specpdl (); do_specbind (sym, specpdl_ptr - 1, value); break; } @@ -3243,12 +3258,10 @@ specbind (Lisp_Object symbol, Lisp_Object value) void record_unwind_protect (Lisp_Object (*function) (Lisp_Object), Lisp_Object arg) { - if (specpdl_ptr == specpdl + specpdl_size) - grow_specpdl (); specpdl_ptr->unwind.kind = SPECPDL_UNWIND; specpdl_ptr->unwind.func = function; specpdl_ptr->unwind.arg = arg; - specpdl_ptr++; + grow_specpdl (); } void diff --git a/src/fileio.c b/src/fileio.c index 89ae89e1613..c3566390130 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -159,11 +159,13 @@ static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t, struct coding_system *); +/* Signal a file-access failure. STRING describes the failure, + DATA the file that was involved, and ERRORNO the errno value. */ + void -report_file_error (const char *string, Lisp_Object data) +report_file_errno (char const *string, Lisp_Object data, int errorno) { Lisp_Object errstring; - int errorno = errno; char *str; synchronize_system_messages_locale (); @@ -196,6 +198,12 @@ report_file_error (const char *string, Lisp_Object data) } } +void +report_file_error (char const *string, Lisp_Object data) +{ + report_file_errno (string, data, errno); +} + Lisp_Object close_file_unwind (Lisp_Object fd) { @@ -2019,11 +2027,8 @@ entries (depending on how Emacs was built). */) { /* CopyFile doesn't set errno when it fails. By far the most "popular" reason is that the target is read-only. */ - if (GetLastError () == 5) - errno = EACCES; - else - errno = EPERM; - report_file_error ("Copying file", Fcons (file, Fcons (newname, Qnil))); + report_file_errno ("Copying file", Fcons (file, Fcons (newname, Qnil)), + GetLastError () == 5 ? EACCES : EPERM); } /* CopyFile retains the timestamp by default. */ else if (NILP (keep_time)) @@ -2084,36 +2089,25 @@ entries (depending on how Emacs was built). */) if (out_st.st_mode != 0 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino) - { - errno = 0; - report_file_error ("Input and output files are the same", - Fcons (file, Fcons (newname, Qnil))); - } + report_file_errno ("Input and output files are the same", + Fcons (file, Fcons (newname, Qnil)), 0); /* We can copy only regular files. */ if (!S_ISREG (st.st_mode)) - { - /* Get a better looking error message. */ - errno = S_ISDIR (st.st_mode) ? EISDIR : EINVAL; - report_file_error ("Non-regular file", Fcons (file, Qnil)); - } + report_file_errno ("Non-regular file", Fcons (file, Qnil), + S_ISDIR (st.st_mode) ? EISDIR : EINVAL); -#ifdef MSDOS - /* System's default file type was set to binary by _fmode in emacs.c. */ - ofd = emacs_open (SDATA (encoded_newname), - O_WRONLY | O_TRUNC | O_CREAT - | (NILP (ok_if_already_exists) ? O_EXCL : 0), - S_IREAD | S_IWRITE); -#else /* not MSDOS */ { - mode_t new_mask = !NILP (preserve_uid_gid) ? 0600 : 0666; - new_mask &= st.st_mode; +#ifndef MSDOS + int new_mask = st.st_mode & (!NILP (preserve_uid_gid) ? 0600 : 0666); +#else + int new_mask = S_IREAD | S_IWRITE; +#endif ofd = emacs_open (SSDATA (encoded_newname), (O_WRONLY | O_TRUNC | O_CREAT | (NILP (ok_if_already_exists) ? O_EXCL : 0)), new_mask); } -#endif /* not MSDOS */ if (ofd < 0) report_file_error ("Opening output file", Fcons (newname, Qnil)); @@ -2122,7 +2116,7 @@ entries (depending on how Emacs was built). */) immediate_quit = 1; QUIT; while ((n = emacs_read (ifd, buf, sizeof buf)) > 0) - if (emacs_write (ofd, buf, n) != n) + if (emacs_write_sig (ofd, buf, n) != n) report_file_error ("I/O error", Fcons (newname, Qnil)); immediate_quit = 0; @@ -2609,7 +2603,11 @@ Use `file-symlink-p' to test for such links. */) call the corresponding file handler. */ handler = Ffind_file_name_handler (absname, Qfile_exists_p); if (!NILP (handler)) - return call2 (handler, Qfile_exists_p, absname); + { + Lisp_Object result = call2 (handler, Qfile_exists_p, absname); + errno = 0; + return result; + } absname = ENCODE_FILE (absname); @@ -2706,7 +2704,6 @@ If there is no error, returns nil. */) (Lisp_Object filename, Lisp_Object string) { Lisp_Object handler, encoded_filename, absname; - int fd; CHECK_STRING (filename); absname = Fexpand_file_name (filename, Qnil); @@ -2721,10 +2718,8 @@ If there is no error, returns nil. */) encoded_filename = ENCODE_FILE (absname); - fd = emacs_open (SSDATA (encoded_filename), O_RDONLY, 0); - if (fd < 0) + if (faccessat (AT_FDCWD, SSDATA (encoded_filename), R_OK, AT_EACCESS) != 0) report_file_error (SSDATA (string), Fcons (filename, Qnil)); - emacs_close (fd); return Qnil; } @@ -2833,7 +2828,11 @@ searchable directory. */) call the corresponding file handler. */ handler = Ffind_file_name_handler (absname, Qfile_accessible_directory_p); if (!NILP (handler)) - return call2 (handler, Qfile_accessible_directory_p, absname); + { + Lisp_Object r = call2 (handler, Qfile_accessible_directory_p, absname); + errno = 0; + return r; + } absname = ENCODE_FILE (absname); return file_accessible_directory_p (SSDATA (absname)) ? Qt : Qnil; @@ -3345,7 +3344,7 @@ otherwise, if FILE2 does not exist, the answer is t. */) if (stat (SSDATA (absname2), &st2) < 0) return Qt; - return (EMACS_TIME_GT (get_stat_mtime (&st1), get_stat_mtime (&st2)) + return (EMACS_TIME_LT (get_stat_mtime (&st2), get_stat_mtime (&st1)) ? Qt : Qnil); } @@ -4575,8 +4574,8 @@ by calling `format-decode', which see. */) && EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS) { /* If visiting nonexistent file, return nil. */ - errno = save_errno; - report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); + report_file_errno ("Opening input file", Fcons (orig_filename, Qnil), + save_errno); } if (read_quit) @@ -4897,13 +4896,13 @@ This calls `write-region-annotate-functions' at the start, and if (desc < 0) { + int open_errno = errno; #ifdef CLASH_DETECTION - save_errno = errno; if (!auto_saving) unlock_file (lockname); - errno = save_errno; #endif /* CLASH_DETECTION */ UNGCPRO; - report_file_error ("Opening output file", Fcons (filename, Qnil)); + report_file_errno ("Opening output file", Fcons (filename, Qnil), + open_errno); } record_unwind_protect (close_file_unwind, make_number (desc)); @@ -4913,13 +4912,13 @@ This calls `write-region-annotate-functions' at the start, and off_t ret = lseek (desc, offset, SEEK_SET); if (ret < 0) { + int lseek_errno = errno; #ifdef CLASH_DETECTION - save_errno = errno; if (!auto_saving) unlock_file (lockname); - errno = save_errno; #endif /* CLASH_DETECTION */ UNGCPRO; - report_file_error ("Lseek error", Fcons (filename, Qnil)); + report_file_errno ("Lseek error", Fcons (filename, Qnil), + lseek_errno); } } @@ -5317,12 +5316,10 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end, if (coding->produced > 0) { - coding->produced - -= emacs_write (desc, - STRINGP (coding->dst_object) - ? SSDATA (coding->dst_object) - : (char *) BYTE_POS_ADDR (coding->dst_pos_byte), - coding->produced); + char *buf = (STRINGP (coding->dst_object) + ? SSDATA (coding->dst_object) + : (char *) BYTE_POS_ADDR (coding->dst_pos_byte)); + coding->produced -= emacs_write_sig (desc, buf, coding->produced); if (coding->produced) return 0; @@ -5377,36 +5374,19 @@ See Info node `(elisp)Modification Time' for more details. */) return Qnil; } -DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime, - Sclear_visited_file_modtime, 0, 0, 0, - doc: /* Clear out records of last mod time of visited file. -Next attempt to save will certainly not complain of a discrepancy. */) - (void) -{ - current_buffer->modtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS); - current_buffer->modtime_size = -1; - return Qnil; -} - DEFUN ("visited-file-modtime", Fvisited_file_modtime, Svisited_file_modtime, 0, 0, 0, doc: /* Return the current buffer's recorded visited file modification time. The value is a list of the form (HIGH LOW USEC PSEC), like the time values that `file-attributes' returns. If the current buffer has no recorded file modification time, this function returns 0. If the visited file -doesn't exist, HIGH will be -1. +doesn't exist, return -1. See Info node `(elisp)Modification Time' for more details. */) (void) { - if (EMACS_NSECS (current_buffer->modtime) < 0) - { - if (EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS) - { - /* make_lisp_time won't work here if time_t is unsigned. */ - return list4i (-1, 65535, 0, 0); - } - return make_number (0); - } + int ns = EMACS_NSECS (current_buffer->modtime); + if (ns < 0) + return make_number (UNKNOWN_MODTIME_NSECS - ns); return make_lisp_time (current_buffer->modtime); } @@ -5417,12 +5397,22 @@ Useful if the buffer was not read from the file normally or if the file itself has been changed for some known benign reason. An argument specifies the modification time value to use \(instead of that of the visited file), in the form of a list -\(HIGH LOW USEC PSEC) as returned by `current-time'. */) - (Lisp_Object time_list) +\(HIGH LOW USEC PSEC) or an integer flag as returned by +`visited-file-modtime'. */) + (Lisp_Object time_flag) { - if (!NILP (time_list)) + if (!NILP (time_flag)) { - current_buffer->modtime = lisp_time_argument (time_list); + EMACS_TIME mtime; + if (INTEGERP (time_flag)) + { + CHECK_RANGED_INTEGER (time_flag, -1, 0); + mtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS - XINT (time_flag)); + } + else + mtime = lisp_time_argument (time_flag); + + current_buffer->modtime = mtime; current_buffer->modtime_size = -1; } else @@ -6123,7 +6113,6 @@ This includes interactive calls to `delete-file' and defsubr (&Swrite_region); defsubr (&Scar_less_than_car); defsubr (&Sverify_visited_file_modtime); - defsubr (&Sclear_visited_file_modtime); defsubr (&Svisited_file_modtime); defsubr (&Sset_visited_file_modtime); 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/>. */ #include "systime.h" #ifdef WINDOWSNT #include <share.h> +#include <sys/socket.h> /* for fcntl */ #include "w32.h" /* for dostounix_filename */ #endif @@ -380,9 +381,9 @@ rename_lock_file (char const *old, char const *new, bool force) #endif } -/* Create the lock file FILE with contents CONTENTS. Return 0 if +/* Create the lock file LFNAME with contents LOCK_INFO_STR. Return 0 if successful, an errno value on failure. If FORCE, remove any - existing FILE if necessary. */ + existing LFNAME if necessary. */ static int create_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) memcpy (nonce, lfname, lfdirlen); strcpy (nonce + lfdirlen, nonce_base); -#if HAVE_MKSTEMP - /* Prefer mkstemp if available, as it avoids a race between +#if HAVE_MKOSTEMP + /* Prefer mkostemp to mkstemp, as it avoids a window where FD is + temporarily open without close-on-exec. */ + fd = mkostemp (nonce, O_BINARY | O_CLOEXEC); + need_fchmod = 1; +#elif HAVE_MKSTEMP + /* Prefer mkstemp to mktemp, as it avoids a race between mktemp and emacs_open. */ fd = mkstemp (nonce); need_fchmod = 1; @@ -432,7 +438,11 @@ create_lock_file (char *lfname, char *lock_info_str, bool force) err = errno; else { - ptrdiff_t lock_info_len = strlen (lock_info_str); + ptrdiff_t lock_info_len; +#if ! HAVE_MKOSTEMP + fcntl (fd, F_SETFD, FD_CLOEXEC); +#endif + lock_info_len = strlen (lock_info_str); err = 0; if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len || (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. */); defsubr (&Ssecure_hash); defsubr (&Slocale_info); - { - struct hash_table_test - eq = { Qeq, Qnil, Qnil, NULL, hashfn_eq }, - eql = { Qeql, Qnil, Qnil, cmpfn_eql, hashfn_eql }, - equal = { Qequal, Qnil, Qnil, cmpfn_equal, hashfn_equal }; - hashtest_eq = eq; - hashtest_eql = eql; - hashtest_equal = equal; - } + hashtest_eq.name = Qeq; + hashtest_eq.user_hash_function = Qnil; + hashtest_eq.user_cmp_function = Qnil; + hashtest_eq.cmpfn = 0; + hashtest_eq.hashfn = hashfn_eq; + + hashtest_eql.name = Qeql; + hashtest_eql.user_hash_function = Qnil; + hashtest_eql.user_cmp_function = Qnil; + hashtest_eql.cmpfn = cmpfn_eql; + hashtest_eql.hashfn = hashfn_eql; + + hashtest_equal.name = Qequal; + hashtest_equal.user_hash_function = Qnil; + hashtest_equal.user_cmp_function = Qnil; + hashtest_equal.cmpfn = cmpfn_equal; + hashtest_equal.hashfn = hashfn_equal; } diff --git a/src/frame.c b/src/frame.c index 6ecc7147c18..648687a7cb4 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1855,7 +1855,7 @@ See `redirect-frame-focus'. */) /* Return the value of frame parameter PROP in frame FRAME. */ #ifdef HAVE_WINDOW_SYSTEM -#if !HAVE_NS && !defined(WINDOWSNT) +#if !HAVE_NS && !defined (WINDOWSNT) static #endif Lisp_Object 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 GNUTLS_STAGE_TRANSPORT_POINTERS_SET, GNUTLS_STAGE_HANDSHAKE_TRIED, - GNUTLS_STAGE_READY, + GNUTLS_STAGE_READY } gnutls_initstage_t; #define GNUTLS_EMACS_ERROR_NOT_LOADED GNUTLS_E_APPLICATION_ERROR_MIN + 1 diff --git a/src/image.c b/src/image.c index 7ecd59d27b4..c085e6e63eb 100644 --- a/src/image.c +++ b/src/image.c @@ -316,7 +316,6 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file) int xhot, yhot, result; ptrdiff_t id; Lisp_Object found; - int fd; char *filename; /* Look for an existing bitmap with the same name. */ @@ -332,10 +331,8 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file) } /* Search bitmap-file-path for the file, if appropriate. */ - fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil); - if (fd < 0) + if (openp (Vx_bitmap_file_path, file, Qnil, &found, make_number (R_OK)) < 0) return -1; - emacs_close (fd); filename = SSDATA (found); @@ -2260,7 +2257,8 @@ x_find_image_file (Lisp_Object file) else { file_found = ENCODE_FILE (file_found); - close (fd); + if (fd != -2) + emacs_close (fd); } return file_found; @@ -8054,7 +8052,7 @@ imagemagick_load_image (struct frame *f, struct image *img, init_color_table (); -#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS +#if defined (HAVE_MAGICKEXPORTIMAGEPIXELS) && ! defined (HAVE_NS) if (imagemagick_render_type != 0) { /* Magicexportimage is normally faster than pixelpushing. This diff --git a/src/inotify.c b/src/inotify.c index 01fb34a5c4a..f4f850bf180 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -71,9 +71,8 @@ static Lisp_Object Qunmount; /* IN_UNMOUNT */ # define IN_ONLYDIR 0 #endif -enum { uninitialized = -100 }; /* File handle for inotify. */ -static int inotifyfd = uninitialized; +static int inotifyfd = -1; /* Assoc list of files being watched. Format: @@ -268,8 +267,10 @@ aspect_to_inotifymask (Lisp_Object aspect) DEFUN ("inotify-add-watch", Finotify_add_watch, Sinotify_add_watch, 3, 3, 0, doc: /* Add a watch for FILE-NAME to inotify. -A WATCH-DESCRIPTOR is returned on success. ASPECT might be one of the following -symbols or a list of those symbols: +Return a watch descriptor. The watch will look for ASPECT events and +invoke CALLBACK when an event occurs. + +ASPECT might be one of the following symbols or a list of those symbols: access attrib @@ -288,7 +289,7 @@ all-events or t move close -The following symbols can also be added to a list of aspects +The following symbols can also be added to a list of aspects: dont-follow excl-unlink @@ -296,9 +297,8 @@ mask-add oneshot onlydir -Watching a directory is not recursive. CALLBACK gets called in case of an -event. It gets passed a single argument EVENT which contains an event structure -of the format +Watching a directory is not recursive. CALLBACK is passed a single argument +EVENT which contains an event structure of the format (WATCH-DESCRIPTOR ASPECTS NAME COOKIE) @@ -331,16 +331,13 @@ is managed internally and there is no corresponding inotify_init. Use CHECK_STRING (file_name); - if (inotifyfd == uninitialized) + if (inotifyfd < 0) { inotifyfd = inotify_init1 (IN_NONBLOCK|IN_CLOEXEC); - if (inotifyfd == -1) - { - inotifyfd = uninitialized; - xsignal1 - (Qfile_notify_error, - build_string ("File watching feature (inotify) is not available")); - } + if (inotifyfd < 0) + xsignal1 + (Qfile_notify_error, + build_string ("File watching feature (inotify) is not available")); watch_list = Qnil; add_read_fd (inotifyfd, &inotify_callback, NULL); } @@ -390,9 +387,9 @@ See inotify_rm_watch(2) for more information. /* Cleanup if no more files are watched. */ if (NILP (watch_list)) { - close (inotifyfd); + emacs_close (inotifyfd); delete_read_fd (inotifyfd); - inotifyfd = uninitialized; + inotifyfd = -1; } return Qt; diff --git a/src/keyboard.c b/src/keyboard.c index 39535f5cd71..b6eb9e6ad15 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -7008,7 +7008,7 @@ tty_read_avail_input (struct terminal *terminal, { nread = emacs_read (fileno (tty->input), (char *) cbuf, n_to_read); /* POSIX infers that processes which are not in the session leader's - process group won't get SIGHUP's at logout time. BSDI adheres to + process group won't get SIGHUPs at logout time. BSDI adheres to this part standard and returns -1 from read (0) with errno==EIO when the control tty is taken away. Jeffrey Honig <jch@bsdi.com> says this is generally safe. */ diff --git a/src/lisp.h b/src/lisp.h index 9af69c61da8..acd21089655 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -365,9 +365,9 @@ enum enum_USE_LSB_TAG { USE_LSB_TAG = 0 }; #define INTMASK (EMACS_INT_MAX >> (INTTYPEBITS - 1)) #define case_Lisp_Int case Lisp_Int0: case Lisp_Int1 -/* Idea stolen from GDB. MSVC doesn't support enums in bitfields, - and xlc complains vociferously about them. */ -#if defined _MSC_VER || defined __IBMC__ +/* Idea stolen from GDB. Pedantic GCC complains about enum bitfields, + MSVC doesn't support them, and xlc complains vociferously about them. */ +#if defined __STRICT_ANSI__ || defined _MSC_VER || defined __IBMC__ #define ENUM_BF(TYPE) unsigned int #else #define ENUM_BF(TYPE) enum TYPE @@ -400,7 +400,7 @@ enum Lisp_Type /* Cons. XCONS (object) points to a struct Lisp_Cons. */ Lisp_Cons = 6, - Lisp_Float = 7, + Lisp_Float = 7 }; /* This is the set of data types that share a common structure. @@ -430,7 +430,7 @@ enum Lisp_Fwd_Type Lisp_Fwd_Bool, /* Fwd to a C boolean var. */ Lisp_Fwd_Obj, /* Fwd to a C Lisp_Object variable. */ Lisp_Fwd_Buffer_Obj, /* Fwd to a Lisp_Object field of buffers. */ - Lisp_Fwd_Kboard_Obj, /* Fwd to a Lisp_Object field of kboards. */ + Lisp_Fwd_Kboard_Obj /* Fwd to a Lisp_Object field of kboards. */ }; /* If you want to define a new Lisp data type, here are some @@ -2614,11 +2614,16 @@ CHECK_NUMBER_CDR (Lisp_Object x) minargs, maxargs, lname, intspec, 0}; \ Lisp_Object fnname #else /* not _MSC_VER */ +# if __STDC_VERSION__ < 199901 +# define DEFUN_FUNCTION_INIT(fnname, maxargs) (Lisp_Object (*) (void)) fnname +# else +# define DEFUN_FUNCTION_INIT(fnname, maxargs) .a ## maxargs = fnname +# endif #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ static struct Lisp_Subr alignas (GCALIGNMENT) sname = \ { { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \ - { .a ## maxargs = fnname }, \ + { DEFUN_FUNCTION_INIT (fnname, maxargs) }, \ minargs, maxargs, lname, intspec, 0}; \ Lisp_Object fnname #endif @@ -3740,7 +3745,6 @@ extern Lisp_Object string_to_number (char const *, int, bool); extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object), Lisp_Object); extern void dir_warning (const char *, Lisp_Object); -extern void close_load_descs (void); extern void init_obarray (void); extern void init_lread (void); extern void syms_of_lread (void); @@ -3896,6 +3900,7 @@ extern Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object); EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */ extern Lisp_Object close_file_unwind (Lisp_Object); extern Lisp_Object restore_point_unwind (Lisp_Object); +extern _Noreturn void report_file_errno (const char *, Lisp_Object, int); extern _Noreturn void report_file_error (const char *, Lisp_Object); extern bool internal_delete_file (Lisp_Object); extern Lisp_Object emacs_readlinkat (int, const char *); @@ -4001,7 +4006,7 @@ extern Lisp_Object Qvisible; extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object); extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object); extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object); -#if HAVE_NS || defined(WINDOWSNT) +#if HAVE_NS || defined WINDOWSNT extern Lisp_Object get_frame_param (struct frame *, Lisp_Object); #endif extern void frames_discard_buffer (Lisp_Object); @@ -4073,11 +4078,11 @@ extern void delete_keyboard_wait_descriptor (int); extern void add_gpm_wait_descriptor (int); extern void delete_gpm_wait_descriptor (int); #endif -extern void close_process_descs (void); extern void init_process_emacs (void); extern void syms_of_process (void); extern void setup_process_coding_systems (Lisp_Object); +/* Defined in callproc.c. */ #ifndef DOS_NT _Noreturn #endif @@ -4169,6 +4174,8 @@ extern int emacs_open (const char *, int, int); extern int emacs_close (int); extern ptrdiff_t emacs_read (int, char *, ptrdiff_t); extern ptrdiff_t emacs_write (int, const char *, ptrdiff_t); +extern ptrdiff_t emacs_write_sig (int, char const *, ptrdiff_t); +extern void emacs_perror (char const *); extern void unlock_all_files (void); extern void lock_file (Lisp_Object); diff --git a/src/lread.c b/src/lread.c index 06badce12be..f0423f166dd 100644 --- a/src/lread.c +++ b/src/lread.c @@ -95,9 +95,6 @@ static Lisp_Object Qload_in_progress; It must be set to nil before all top-level calls to read0. */ static Lisp_Object read_objects; -/* List of descriptors now open for Fload. */ -static Lisp_Object load_descriptor_list; - /* File for get_file_char to read from. Use by load. */ static FILE *instream; @@ -149,7 +146,6 @@ static void readevalloop (Lisp_Object, FILE *, Lisp_Object, bool, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); static Lisp_Object load_unwind (Lisp_Object); -static Lisp_Object load_descriptor_unwind (Lisp_Object); /* Functions that read one byte from the current source READCHARFUN or unreads one byte. If the integer argument C is -1, it returns @@ -827,7 +823,7 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun) { bool rv = 0; enum { - NOMINAL, AFTER_FIRST_DASH, AFTER_ASTERIX, + NOMINAL, AFTER_FIRST_DASH, AFTER_ASTERIX } beg_end_state = NOMINAL; bool in_file_vars = 0; @@ -1328,11 +1324,8 @@ Return t if the file exists and loads successfully. */) } record_unwind_protect (load_unwind, make_save_pointer (stream)); - record_unwind_protect (load_descriptor_unwind, load_descriptor_list); specbind (Qload_file_name, found); specbind (Qinhibit_file_name_operation, Qnil); - load_descriptor_list - = Fcons (make_number (fileno (stream)), load_descriptor_list); specbind (Qload_in_progress, Qt); instream = stream; @@ -1395,26 +1388,6 @@ load_unwind (Lisp_Object arg) /* Used as unwind-protect function in load. */ } return Qnil; } - -static Lisp_Object -load_descriptor_unwind (Lisp_Object oldlist) -{ - load_descriptor_list = oldlist; - return Qnil; -} - -/* Close all descriptors in use for Floads. - This is used when starting a subprocess. */ - -void -close_load_descs (void) -{ -#ifndef WINDOWSNT - Lisp_Object tail; - for (tail = load_descriptor_list; CONSP (tail); tail = XCDR (tail)) - emacs_close (XFASTINT (XCAR (tail))); -#endif -} static bool complete_filename_p (Lisp_Object pathname) @@ -1439,8 +1412,8 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */) { Lisp_Object file; int fd = openp (path, filename, suffixes, &file, predicate); - if (NILP (predicate) && fd > 0) - close (fd); + if (NILP (predicate) && fd >= 0) + emacs_close (fd); return file; } @@ -1448,14 +1421,15 @@ static Lisp_Object Qdir_ok; /* Search for a file whose name is STR, looking in directories in the Lisp list PATH, and trying suffixes from SUFFIX. - On success, returns a file descriptor. On failure, returns -1. + On success, return a file descriptor (or 1 or -2 as described below). + On failure, return -1 and set errno. SUFFIXES is a list of strings containing possible suffixes. The empty suffix is automatically added if the list is empty. PREDICATE non-nil means don't open the files, just look for one that satisfies the predicate. In this case, - returns 1 on success. The predicate can be a lisp function or + return 1 on success. The predicate can be a lisp function or an integer to pass to `access' (in which case file-name-handlers are ignored). @@ -1467,7 +1441,8 @@ static Lisp_Object Qdir_ok; but store the found remote file name in *STOREPTR. */ int -openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *storeptr, Lisp_Object predicate) +openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, + Lisp_Object *storeptr, Lisp_Object predicate) { ptrdiff_t fn_size = 100; char buf[100]; @@ -1478,6 +1453,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6; Lisp_Object string, tail, encoded_fn; ptrdiff_t max_suffix_len = 0; + int last_errno = ENOENT; CHECK_STRING (str); @@ -1547,14 +1523,22 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate)) { bool exists; + last_errno = ENOENT; if (NILP (predicate)) exists = !NILP (Ffile_readable_p (string)); else { Lisp_Object tmp = call1 (predicate, string); - exists = !NILP (tmp) - && (EQ (tmp, Qdir_ok) - || NILP (Ffile_directory_p (string))); + if (NILP (tmp)) + exists = 0; + else if (EQ (tmp, Qdir_ok) + || NILP (Ffile_directory_p (string))) + exists = 1; + else + { + exists = 0; + last_errno = EISDIR; + } } if (exists) @@ -1576,21 +1560,36 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto /* Check that we can access or open it. */ if (NATNUMP (predicate)) - fd = (((XFASTINT (predicate) & ~INT_MAX) == 0 - && (faccessat (AT_FDCWD, pfn, XFASTINT (predicate), + { + fd = -1; + if (INT_MAX < XFASTINT (predicate)) + last_errno = EINVAL; + else if (faccessat (AT_FDCWD, pfn, XFASTINT (predicate), AT_EACCESS) == 0) - && ! file_directory_p (pfn)) - ? 1 : -1); + { + if (file_directory_p (pfn)) + last_errno = EISDIR; + else + fd = 1; + } + } else { - struct stat st; fd = emacs_open (pfn, O_RDONLY, 0); - if (fd >= 0 - && (fstat (fd, &st) != 0 || S_ISDIR (st.st_mode))) + if (fd < 0) + last_errno = errno; + else { - emacs_close (fd); - fd = -1; + struct stat st; + int err = (fstat (fd, &st) != 0 ? errno + : S_ISDIR (st.st_mode) ? EISDIR : 0); + if (err) + { + last_errno = err; + emacs_close (fd); + fd = -1; + } } } @@ -1609,6 +1608,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto } UNGCPRO; + errno = last_errno; return -1; } @@ -4349,9 +4349,6 @@ init_lread (void) load_in_progress = 0; Vload_file_name = Qnil; - - load_descriptor_list = Qnil; - Vstandard_input = Qt; Vloads_in_progress = Qnil; } @@ -4624,9 +4621,6 @@ variables, this must be set in the first line of a file. */); /* Vsource_directory was initialized in init_lread. */ - load_descriptor_list = Qnil; - staticpro (&load_descriptor_list); - DEFSYM (Qcurrent_load_list, "current-load-list"); DEFSYM (Qstandard_input, "standard-input"); 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) : \ $(NT_INC)/sys/file.h \ $(NT_INC)/unistd.h \ $(GNU_LIB)/close-stream.h \ - $(GNU_LIB)/ignore-value.h \ $(ATIMER_H) \ $(BUFFER_H) \ $(CHARACTER_H) \ @@ -1407,7 +1406,6 @@ $(BLD)/sysdep.$(O) : \ $(NT_INC)/sys/stat.h \ $(NT_INC)/unistd.h \ $(GNU_LIB)/execinfo.h \ - $(GNU_LIB)/ignore-value.h \ $(GNU_LIB)/utimens.h \ $(CONFIG_H) \ $(C_CTYPE_H) \ diff --git a/src/nsfns.m b/src/nsfns.m index b8f46e461fa..6eebb4d2567 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -885,7 +885,7 @@ ns_appkit_version_str (void) #ifdef NS_IMPL_GNUSTEP sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION)); -#elif defined(NS_IMPL_COCOA) +#elif defined (NS_IMPL_COCOA) sprintf(tmp, "apple-appkit-%.2f", NSAppKitVersionNumber); #else tmp = "ns-unknown"; @@ -902,7 +902,7 @@ ns_appkit_version_int (void) { #ifdef NS_IMPL_GNUSTEP return GNUSTEP_GUI_MAJOR_VERSION * 100 + GNUSTEP_GUI_MINOR_VERSION; -#elif defined(NS_IMPL_COCOA) +#elif defined (NS_IMPL_COCOA) return (int)NSAppKitVersionNumber; #endif return 0; @@ -2493,7 +2493,7 @@ Internal use only, use `display-monitor-attributes-list' instead. */) vy = (short) (primary_display_height - vfr.size.height - vfr.origin.y); } - + m->geom.x = (short) fr.origin.x; m->geom.y = y; m->geom.width = (unsigned short) fr.size.width; 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; if (trackingMenu == 0) return; /*fprintf (stderr, "Updating menu '%s'\n", [[self title] UTF8String]); NSLog (@"%@\n", event); */ -#if ! defined(NS_IMPL_COCOA) || \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 +#if (! defined (NS_IMPL_COCOA) \ + || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) /* Don't know how to do this for anything other than OSX >= 10.5 This is wrong, as it might run Lisp code in the event loop. */ ns_update_menubar (frame, true, self); @@ -1240,7 +1240,7 @@ update_frame_tool_bar (FRAME_PTR f) #ifdef NS_IMPL_GNUSTEP [self insertItemWithItemIdentifier: identifier atIndex: idx]; #endif - + [item setTag: tag]; [item setEnabled: enabled]; diff --git a/src/nsterm.m b/src/nsterm.m index 97a6313489d..d7cea5c189a 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -3603,7 +3603,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, /* Inform fd_handler that select should be called */ c = 'g'; - emacs_write (selfds[1], &c, 1); + emacs_write_sig (selfds[1], &c, 1); } else if (nr == 0 && timeout) { @@ -3636,7 +3636,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, if (nr > 0 && readfds) { c = 's'; - emacs_write (selfds[1], &c, 1); + emacs_write_sig (selfds[1], &c, 1); } unblock_input (); @@ -4142,7 +4142,7 @@ ns_term_init (Lisp_Object display_name) if (selfds[0] == -1) { - if (pipe (selfds) == -1) + if (pipe2 (selfds, O_CLOEXEC) != 0) { fprintf (stderr, "Failed to create pipe: %s\n", emacs_strerror (errno)); @@ -4419,6 +4419,16 @@ ns_term_shutdown (int sig) /* NSTRACE (sendEvent); */ /*fprintf (stderr, "received event of type %d\t%d\n", type);*/ +#ifdef NS_IMPL_GNUSTEP + // Keyboard events aren't propagated to file dialogs for some reason. + if ([NSApp modalWindow] != nil && + (type == NSKeyDown || type == NSKeyUp || type == NSFlagsChanged)) + { + [[NSApp modalWindow] sendEvent: theEvent]; + return; + } +#endif + if (type == NSApplicationDefined) { switch ([theEvent data2]) diff --git a/src/print.c b/src/print.c index 09519d93cfe..01e490dcbad 100644 --- a/src/print.c +++ b/src/print.c @@ -1765,9 +1765,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) } else if (WINDOWP (obj)) { - int len; - strout ("#<window ", -1, -1, printcharfun); - len = sprintf (buf, "%p", XWINDOW (obj)); + void *ptr = XWINDOW (obj); + int len = sprintf (buf, "#<window %p", ptr); strout (buf, len, len, printcharfun); if (BUFFERP (XWINDOW (obj)->contents)) { @@ -1798,6 +1797,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) ptrdiff_t real_size, size; int len; #if 0 + void *ptr = h; strout ("#<hash-table", -1, -1, printcharfun); if (SYMBOLP (h->test)) { @@ -1810,9 +1810,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) len = sprintf (buf, "%"pD"d/%"pD"d", h->count, ASIZE (h->next)); strout (buf, len, len, printcharfun); } - len = sprintf (buf, " %p", h); + len = sprintf (buf, " %p>", ptr); strout (buf, len, len, printcharfun); - PRINTCHAR ('>'); #endif /* Implement a readable output, e.g.: #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */ @@ -1892,6 +1891,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) else if (FRAMEP (obj)) { int len; + void *ptr = XFRAME (obj); Lisp_Object frame_name = XFRAME (obj)->name; strout ((FRAME_LIVE_P (XFRAME (obj)) @@ -1907,9 +1907,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) frame_name = build_string ("*INVALID*FRAME*NAME*"); } print_string (frame_name, printcharfun); - len = sprintf (buf, " %p", XFRAME (obj)); + len = sprintf (buf, " %p>", ptr); strout (buf, len, len, printcharfun); - PRINTCHAR ('>'); } else if (FONTP (obj)) { diff --git a/src/process.c b/src/process.c index 2e2610ffde4..dc37bfe7067 100644 --- a/src/process.c +++ b/src/process.c @@ -135,6 +135,37 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, EMACS_TIME *, void *); #endif +#ifndef SOCK_CLOEXEC +# define SOCK_CLOEXEC 0 +#endif + +#ifndef HAVE_ACCEPT4 + +/* Emulate GNU/Linux accept4 and socket well enough for this module. */ + +static int +close_on_exec (int fd) +{ + if (0 <= fd) + fcntl (fd, F_SETFD, FD_CLOEXEC); + return fd; +} + +static int +accept4 (int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) +{ + return close_on_exec (accept (sockfd, addr, addrlen)); +} + +static int +process_socket (int domain, int type, int protocol) +{ + return close_on_exec (socket (domain, type, protocol)); +} +# undef socket +# define socket(domain, type, protocol) process_socket (domain, type, protocol) +#endif + /* Work around GCC 4.7.0 bug with strict overflow checking; see <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>. These lines can be removed once the GCC bug is fixed. */ @@ -1782,6 +1813,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) { int inchannel, outchannel; pid_t pid; + int vfork_errno; int sv[2]; #ifndef WINDOWSNT int wait_child_setup[2]; @@ -1816,47 +1848,30 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) else #endif /* HAVE_PTYS */ { - int tem; - tem = pipe (sv); - if (tem < 0) + if (pipe2 (sv, O_CLOEXEC) != 0) report_file_error ("Creating pipe", Qnil); inchannel = sv[0]; forkout = sv[1]; - tem = pipe (sv); - if (tem < 0) + if (pipe2 (sv, O_CLOEXEC) != 0) { + int pipe_errno = errno; emacs_close (inchannel); emacs_close (forkout); - report_file_error ("Creating pipe", Qnil); + report_file_errno ("Creating pipe", Qnil, pipe_errno); } outchannel = sv[1]; forkin = sv[0]; } #ifndef WINDOWSNT - { - int tem; - - tem = pipe (wait_child_setup); - if (tem < 0) - report_file_error ("Creating pipe", Qnil); - tem = fcntl (wait_child_setup[1], F_GETFD, 0); - if (tem >= 0) - tem = fcntl (wait_child_setup[1], F_SETFD, tem | FD_CLOEXEC); - if (tem < 0) - { - emacs_close (wait_child_setup[0]); - emacs_close (wait_child_setup[1]); - report_file_error ("Setting file descriptor flags", Qnil); - } - } + if (pipe2 (wait_child_setup, O_CLOEXEC) != 0) + report_file_error ("Creating pipe", Qnil); #endif fcntl (inchannel, F_SETFL, O_NONBLOCK); fcntl (outchannel, F_SETFL, O_NONBLOCK); - /* Record this as an active process, with its channels. - As a result, child_setup will close Emacs's side of the pipes. */ + /* Record this as an active process, with its channels. */ chan_process[inchannel] = process; XPROCESS (process)->infd = inchannel; XPROCESS (process)->outfd = outchannel; @@ -1933,7 +1948,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) tcgetattr (xforkin, &t); t.c_lflag = LDISC1; if (tcsetattr (xforkin, TCSANOW, &t) < 0) - emacs_write (1, "create_process/tcsetattr LDISC1 failed\n", 39); + emacs_perror ("create_process/tcsetattr LDISC1"); } #else #if defined (NTTYDISC) && defined (TIOCSETD) @@ -1980,10 +1995,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) if (xforkin < 0) { - emacs_write (1, "Couldn't open the pty terminal ", 31); - emacs_write (1, pty_name, strlen (pty_name)); - emacs_write (1, "\n", 1); - _exit (1); + emacs_perror (pty_name); + _exit (EXIT_CANCELED); } } @@ -1995,12 +2008,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) SETUP_SLAVE_PTY; } #endif /* SETUP_SLAVE_PTY */ -#ifdef AIX - /* On AIX, we've disabled SIGHUP above once we start a child on a pty. - Now reenable it in the child, so it will die when we want it to. */ - if (pty_flag) - signal (SIGHUP, SIG_DFL); -#endif #endif /* HAVE_PTYS */ signal (SIGINT, SIG_DFL); @@ -2026,6 +2033,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) /* Back in the parent process. */ + vfork_errno = errno; XPROCESS (process)->pid = pid; if (pid >= 0) XPROCESS (process)->alive = 1; @@ -2040,6 +2048,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) emacs_close (forkin); if (forkin != forkout && forkout >= 0) emacs_close (forkout); + report_file_errno ("Doing vfork", Qnil, vfork_errno); } else { @@ -2085,10 +2094,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) } #endif } - - /* Now generate the error if vfork failed. */ - if (pid < 0) - report_file_error ("Doing vfork", Qnil); } void @@ -3323,7 +3328,8 @@ usage: (make-network-process &rest ARGS) */) retry_connect: #endif - s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol); + s = socket (lres->ai_family, lres->ai_socktype | SOCK_CLOEXEC, + lres->ai_protocol); if (s < 0) { xerrno = errno; @@ -3447,12 +3453,11 @@ usage: (make-network-process &rest ARGS) */) len = sizeof xerrno; eassert (FD_ISSET (s, &fdset)); - if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) == -1) + if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) < 0) report_file_error ("getsockopt failed", Qnil); if (xerrno) - errno = xerrno, report_file_error ("error during connect", Qnil); - else - break; + report_file_errno ("error during connect", Qnil, xerrno); + break; } #endif /* !WINDOWSNT */ @@ -3536,11 +3541,10 @@ usage: (make-network-process &rest ARGS) */) if (is_non_blocking_client) return Qnil; - errno = xerrno; - if (is_server) - report_file_error ("make server process failed", contact); - else - report_file_error ("make client process failed", contact); + report_file_errno ((is_server + ? "make server process failed" + : "make client process failed"), + contact, xerrno); } inch = s; @@ -3713,7 +3717,7 @@ format; see the description of ADDRESS in `make-network-process'. */) int s; Lisp_Object res; - s = socket (AF_INET, SOCK_STREAM, 0); + s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); if (s < 0) return Qnil; @@ -3724,14 +3728,14 @@ format; see the description of ADDRESS in `make-network-process'. */) ifconf.ifc_len = buf_size; if (ioctl (s, SIOCGIFCONF, &ifconf)) { - close (s); + emacs_close (s); xfree (buf); return Qnil; } } while (ifconf.ifc_len == buf_size); - close (s); + emacs_close (s); res = Qnil; ifreq = ifconf.ifc_req; @@ -3869,7 +3873,7 @@ FLAGS is the current flags of the interface. */) error ("interface name too long"); strcpy (rq.ifr_name, SSDATA (ifname)); - s = socket (AF_INET, SOCK_STREAM, 0); + s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); if (s < 0) return Qnil; @@ -3988,7 +3992,7 @@ FLAGS is the current flags of the interface. */) #endif res = Fcons (elt, res); - close (s); + emacs_close (s); return any ? res : Qnil; } @@ -4161,7 +4165,7 @@ server_accept_connection (Lisp_Object server, int channel) } saddr; socklen_t len = sizeof saddr; - s = accept (channel, &saddr.sa, &len); + s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC); if (s < 0) { @@ -4785,20 +4789,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (xerrno == EINTR) no_avail = 1; else if (xerrno == EBADF) - { -#ifdef AIX - /* AIX doesn't handle PTY closure the same way BSD does. On AIX, - the child's closure of the pts gives the parent a SIGHUP, and - the ptc file descriptor is automatically closed, - yielding EBADF here or at select() call above. - So, SIGHUP is ignored (see def of PTY_TTY_NAME_SPRINTF - in m/ibmrt-aix.h), and here we just ignore the select error. - Cleanup occurs c/o status_notify after SIGCHLD. */ - no_avail = 1; /* Cannot depend on values returned */ -#else - emacs_abort (); -#endif - } + emacs_abort (); else error ("select error: %s", emacs_strerror (xerrno)); } @@ -5648,7 +5639,7 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len, written = emacs_gnutls_write (p, cur_buf, cur_len); else #endif - written = emacs_write (outfd, cur_buf, cur_len); + written = emacs_write_sig (outfd, cur_buf, cur_len); rv = (written ? 0 : -1); #ifdef ADAPTIVE_READ_BUFFERING if (p->read_output_delay > 0 @@ -7010,32 +7001,6 @@ setup_process_coding_systems (Lisp_Object process) #endif } -/* Close all descriptors currently in use for communication - with subprocess. This is used in a newly-forked subprocess - to get rid of irrelevant descriptors. */ - -void -close_process_descs (void) -{ -#ifndef DOS_NT - int i; - for (i = 0; i < MAXDESC; i++) - { - Lisp_Object process; - process = chan_process[i]; - if (!NILP (process)) - { - int in = XPROCESS (process)->infd; - int out = XPROCESS (process)->outfd; - if (in >= 0) - emacs_close (in); - if (out >= 0 && in != out) - emacs_close (out); - } - } -#endif -} - DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0, doc: /* Return the (or a) process associated with BUFFER. BUFFER may be a buffer or the name of one. */) diff --git a/src/process.h b/src/process.h index 52142e55e94..89c7e8b1259 100644 --- a/src/process.h +++ b/src/process.h @@ -201,6 +201,14 @@ extern Lisp_Object QCspeed; extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven; extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary; +/* Exit statuses for GNU programs that exec other programs. */ +enum +{ + EXIT_CANCELED = 125, /* Internal error prior to exec attempt. */ + EXIT_CANNOT_INVOKE = 126, /* Program located, but not usable. */ + EXIT_ENOENT = 127 /* Could not find program to exec. */ +}; + /* Defined in callproc.c. */ extern 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. */); profiler_log_size = 10000; DEFSYM (Qprofiler_backtrace_equal, "profiler-backtrace-equal"); - { - struct hash_table_test test - = { Qprofiler_backtrace_equal, Qnil, Qnil, - cmpfn_profiler, hashfn_profiler }; - hashtest_profiler = test; - } + + hashtest_profiler.name = Qprofiler_backtrace_equal; + hashtest_profiler.user_hash_function = Qnil; + hashtest_profiler.user_cmp_function = Qnil; + hashtest_profiler.cmpfn = cmpfn_profiler; + hashtest_profiler.hashfn = hashfn_profiler; defsubr (&Sfunction_equal); diff --git a/src/regex.c b/src/regex.c index 73a735cea65..5024f748884 100644 --- a/src/regex.c +++ b/src/regex.c @@ -531,8 +531,10 @@ init_syntax_once (void) /* Type of source-pattern and string chars. */ #ifdef _MSC_VER typedef unsigned char re_char; +typedef const re_char const_re_char; #else typedef const unsigned char re_char; +typedef re_char const_re_char; #endif typedef char boolean; @@ -2019,7 +2021,7 @@ struct range_table_work_area /* Map a string to the char class it names (if any). */ re_wctype_t -re_wctype (const re_char *str) +re_wctype (const_re_char *str) { const char *string = (const char *) str; if (STREQ (string, "alnum")) return RECC_ALNUM; @@ -2413,7 +2415,8 @@ do { \ } while (0) static reg_errcode_t -regex_compile (const re_char *pattern, size_t size, reg_syntax_t syntax, struct re_pattern_buffer *bufp) +regex_compile (const_re_char *pattern, size_t size, reg_syntax_t syntax, + struct re_pattern_buffer *bufp) { /* We fetch characters from PATTERN here. */ register re_wchar_t c, c1; @@ -3769,7 +3772,7 @@ insert_op2 (re_opcode_t op, unsigned char *loc, int arg1, int arg2, unsigned cha least one character before the ^. */ static boolean -at_begline_loc_p (const re_char *pattern, const re_char *p, reg_syntax_t syntax) +at_begline_loc_p (const_re_char *pattern, const_re_char *p, reg_syntax_t syntax) { re_char *prev = p - 2; boolean odd_backslashes; @@ -3810,7 +3813,7 @@ at_begline_loc_p (const re_char *pattern, const re_char *p, reg_syntax_t syntax) at least one character after the $, i.e., `P < PEND'. */ static boolean -at_endline_loc_p (const re_char *p, const re_char *pend, reg_syntax_t syntax) +at_endline_loc_p (const_re_char *p, const_re_char *pend, reg_syntax_t syntax) { re_char *next = p; boolean next_backslash = *next == '\\'; @@ -3854,7 +3857,8 @@ group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum) Return -1 if fastmap was not updated accurately. */ static int -analyse_first (const re_char *p, const re_char *pend, char *fastmap, const int multibyte) +analyse_first (const_re_char *p, const_re_char *pend, char *fastmap, + const int multibyte) { int j, k; boolean not; @@ -4598,7 +4602,7 @@ static int bcmp_translate (re_char *s1, re_char *s2, /* If the operation is a match against one or more chars, return a pointer to the next operation, else return NULL. */ static re_char * -skip_one_char (const re_char *p) +skip_one_char (const_re_char *p) { switch (*p++) { @@ -4640,7 +4644,7 @@ skip_one_char (const re_char *p) /* Jump over non-matching operations. */ static re_char * -skip_noops (const re_char *p, const re_char *pend) +skip_noops (const_re_char *p, const_re_char *pend) { int mcnt; while (p < pend) @@ -4667,7 +4671,8 @@ skip_noops (const re_char *p, const re_char *pend) /* Non-zero if "p1 matches something" implies "p2 fails". */ static int -mutually_exclusive_p (struct re_pattern_buffer *bufp, const re_char *p1, const re_char *p2) +mutually_exclusive_p (struct re_pattern_buffer *bufp, const_re_char *p1, + const_re_char *p2) { re_opcode_t op2; const boolean multibyte = RE_MULTIBYTE_P (bufp); @@ -4920,8 +4925,8 @@ WEAK_ALIAS (__re_match_2, re_match_2) /* This is a separate function so that we can force an alloca cleanup afterwards. */ static regoff_t -re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1, - size_t size1, const re_char *string2, size_t size2, +re_match_2_internal (struct re_pattern_buffer *bufp, const_re_char *string1, + size_t size1, const_re_char *string2, size_t size2, ssize_t pos, struct re_registers *regs, ssize_t stop) { /* General temporaries. */ @@ -6263,7 +6268,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1, bytes; nonzero otherwise. */ static int -bcmp_translate (const re_char *s1, const re_char *s2, register ssize_t len, +bcmp_translate (const_re_char *s1, const_re_char *s2, register ssize_t len, RE_TRANSLATE_TYPE translate, const int target_multibyte) { register re_char *p1 = s1, *p2 = s2; @@ -6432,7 +6437,7 @@ re_exec (const char *s) the return codes and their meanings.) */ reg_errcode_t -regcomp (regex_t *__restrict preg, const char *__restrict pattern, +regcomp (regex_t *_Restrict_ preg, const char *_Restrict_ pattern, int cflags) { reg_errcode_t ret; @@ -6513,8 +6518,8 @@ WEAK_ALIAS (__regcomp, regcomp) We return 0 if we find a match and REG_NOMATCH if not. */ reg_errcode_t -regexec (const regex_t *__restrict preg, const char *__restrict string, - size_t nmatch, regmatch_t pmatch[__restrict_arr], int eflags) +regexec (const regex_t *_Restrict_ preg, const char *_Restrict_ string, + size_t nmatch, regmatch_t pmatch[_Restrict_arr_], int eflags) { regoff_t ret; struct re_registers regs; diff --git a/src/regex.h b/src/regex.h index 175eed10177..31be0504c9e 100644 --- a/src/regex.h +++ b/src/regex.h @@ -528,31 +528,41 @@ extern int re_exec (const char *); #endif /* GCC 2.95 and later have "__restrict"; C99 compilers have - "restrict", and "configure" may have defined "restrict". */ -#ifndef __restrict -# if ! (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)) -# if defined restrict || 199901L <= __STDC_VERSION__ -# define __restrict restrict -# else -# define __restrict -# endif + "restrict", and "configure" may have defined "restrict". + Other compilers use __restrict, __restrict__, and _Restrict, and + 'configure' might #define 'restrict' to those words, so pick a + different name. */ +#ifndef _Restrict_ +# if 199901L <= __STDC_VERSION__ +# define _Restrict_ restrict +# elif 2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__) +# define _Restrict_ __restrict +# else +# define _Restrict_ # endif #endif -/* For now conditionally define __restrict_arr to expand to nothing. - Ideally we would have a test for the compiler which allows defining - it to restrict. */ -#ifndef __restrict_arr -# define __restrict_arr +/* gcc 3.1 and up support the [restrict] syntax. Don't trust + sys/cdefs.h's definition of __restrict_arr, though, as it + mishandles gcc -ansi -pedantic. */ +#ifndef _Restrict_arr_ +# if ((199901L <= __STDC_VERSION__ \ + || ((3 < __GNUC__ || (3 == __GNUC__ && 1 <= __GNUC_MINOR__)) \ + && !defined __STRICT_ANSI__)) \ + && !defined __GNUG__) +# define _Restrict_arr_ _Restrict_ +# else +# define _Restrict_arr_ +# endif #endif /* POSIX compatibility. */ -extern reg_errcode_t regcomp (regex_t *__restrict __preg, - const char *__restrict __pattern, +extern reg_errcode_t regcomp (regex_t *_Restrict_ __preg, + const char *_Restrict_ __pattern, int __cflags); -extern reg_errcode_t regexec (const regex_t *__restrict __preg, - const char *__restrict __string, size_t __nmatch, - regmatch_t __pmatch[__restrict_arr], +extern reg_errcode_t regexec (const regex_t *_Restrict_ __preg, + const char *_Restrict_ __string, size_t __nmatch, + regmatch_t __pmatch[_Restrict_arr_], int __eflags); extern size_t regerror (int __errcode, const regex_t * __preg, diff --git a/src/search.c b/src/search.c index b4e3cca8269..ff47bb2fecf 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/>. */ #include <config.h> #include "lisp.h" -#include "syntax.h" #include "category.h" #include "character.h" #include "buffer.h" +#include "syntax.h" #include "charset.h" #include "region-cache.h" #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/>. */ #include <unistd.h> +#ifdef __x86_64__ +#define STATIC_HEAP_SIZE (18 * 1024 * 1024) +#else #define STATIC_HEAP_SIZE (13 * 1024 * 1024) +#endif int debug_sheap = 0; 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) static void vox_write (struct sound_device *sd, const char *buffer, ptrdiff_t nbytes) { - if (emacs_write (sd->fd, buffer, nbytes) != nbytes) + if (emacs_write_sig (sd->fd, buffer, nbytes) != nbytes) sound_perror ("Error writing to sound device"); } 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/>. */ #include <config.h> +#define SYNTAX_INLINE EXTERN_INLINE + #include <sys/types.h> #include "lisp.h" @@ -58,54 +60,86 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ For style c (like the nested flag), the flag can be placed on any of the chars. */ -/* These macros extract specific flags from an integer +/* These functions extract specific flags from an integer that holds the syntax code and the flags. */ -#define SYNTAX_FLAGS_COMSTART_FIRST(flags) (((flags) >> 16) & 1) - -#define SYNTAX_FLAGS_COMSTART_SECOND(flags) (((flags) >> 17) & 1) - -#define SYNTAX_FLAGS_COMEND_FIRST(flags) (((flags) >> 18) & 1) - -#define SYNTAX_FLAGS_COMEND_SECOND(flags) (((flags) >> 19) & 1) - -#define SYNTAX_FLAGS_PREFIX(flags) (((flags) >> 20) & 1) +static bool +SYNTAX_FLAGS_COMSTART_FIRST (int flags) +{ + return (flags >> 16) & 1; +} +static bool +SYNTAX_FLAGS_COMSTART_SECOND (int flags) +{ + return (flags >> 17) & 1; +} +static bool +SYNTAX_FLAGS_COMEND_FIRST (int flags) +{ + return (flags >> 18) & 1; +} +static bool +SYNTAX_FLAGS_COMEND_SECOND (int flags) +{ + return (flags >> 19) & 1; +} +static bool +SYNTAX_FLAGS_PREFIX (int flags) +{ + return (flags >> 20) & 1; +} +static bool +SYNTAX_FLAGS_COMMENT_STYLEB (int flags) +{ + return (flags >> 21) & 1; +} +static bool +SYNTAX_FLAGS_COMMENT_STYLEC (int flags) +{ + return (flags >> 23) & 1; +} +static int +SYNTAX_FLAGS_COMMENT_STYLEC2 (int flags) +{ + return (flags >> 22) & 2; /* SYNTAX_FLAGS_COMMENT_STYLEC (flags) * 2 */ +} +static bool +SYNTAX_FLAGS_COMMENT_NESTED (int flags) +{ + return (flags >> 22) & 1; +} -#define SYNTAX_FLAGS_COMMENT_STYLEB(flags) (((flags) >> 21) & 1) -#define SYNTAX_FLAGS_COMMENT_STYLEC(flags) (((flags) >> 23) & 1) -#define SYNTAX_FLAGS_COMMENT_STYLEC2(flags) (((flags) >> 22) & 2) /* C * 2 */ /* FLAGS should be the flags of the main char of the comment marker, e.g. the second for comstart and the first for comend. */ -#define SYNTAX_FLAGS_COMMENT_STYLE(flags, other_flags) \ - (SYNTAX_FLAGS_COMMENT_STYLEB (flags) \ - | SYNTAX_FLAGS_COMMENT_STYLEC2 (flags) \ - | SYNTAX_FLAGS_COMMENT_STYLEC2 (other_flags)) - -#define SYNTAX_FLAGS_COMMENT_NESTED(flags) (((flags) >> 22) & 1) +static int +SYNTAX_FLAGS_COMMENT_STYLE (int flags, int other_flags) +{ + return (SYNTAX_FLAGS_COMMENT_STYLEB (flags) + | SYNTAX_FLAGS_COMMENT_STYLEC2 (flags) + | SYNTAX_FLAGS_COMMENT_STYLEC2 (other_flags)); +} -/* These macros extract a particular flag for a given character. */ +/* Extract a particular flag for a given character. */ -#define SYNTAX_COMEND_FIRST(c) \ - (SYNTAX_FLAGS_COMEND_FIRST (SYNTAX_WITH_FLAGS (c))) -#define SYNTAX_PREFIX(c) (SYNTAX_FLAGS_PREFIX (SYNTAX_WITH_FLAGS (c))) +static bool +SYNTAX_COMEND_FIRST (int c) +{ + return SYNTAX_FLAGS_COMEND_FIRST (SYNTAX_WITH_FLAGS (c)); +} /* We use these constants in place for comment-style and - string-ender-char to distinguish comments/strings started by + string-ender-char to distinguish comments/strings started by comment_fence and string_fence codes. */ -#define ST_COMMENT_STYLE (256 + 1) -#define ST_STRING_STYLE (256 + 2) +enum + { + ST_COMMENT_STYLE = 256 + 1, + ST_STRING_STYLE = 256 + 2 + }; static Lisp_Object Qsyntax_table_p; static Lisp_Object Qsyntax_table, Qscan_error; -#ifndef __GNUC__ -/* Used as a temporary in SYNTAX_ENTRY and other macros in syntax.h, - if not compiled with GCC. No need to mark it, since it is used - only very temporarily. */ -Lisp_Object syntax_temp; -#endif - /* This is the internal form of the parse state used in parse-partial-sexp. */ struct lisp_parse_state @@ -162,14 +196,107 @@ bset_syntax_table (struct buffer *b, Lisp_Object val) bool syntax_prefix_flag_p (int c) { - return SYNTAX_PREFIX (c); + return SYNTAX_FLAGS_PREFIX (SYNTAX_WITH_FLAGS (c)); } struct gl_state_s gl_state; /* Global state of syntax parser. */ -#define INTERVALS_AT_ONCE 10 /* 1 + max-number of intervals +enum { INTERVALS_AT_ONCE = 10 }; /* 1 + max-number of intervals to scan to property-change. */ +/* Set the syntax entry VAL for char C in table TABLE. */ + +static void +SET_RAW_SYNTAX_ENTRY (Lisp_Object table, int c, Lisp_Object val) +{ + CHAR_TABLE_SET (table, c, val); +} + +/* Set the syntax entry VAL for char-range RANGE in table TABLE. + RANGE is a cons (FROM . TO) specifying the range of characters. */ + +static void +SET_RAW_SYNTAX_ENTRY_RANGE (Lisp_Object table, Lisp_Object range, + Lisp_Object val) +{ + Fset_char_table_range (table, range, val); +} + +/* Extract the information from the entry for character C + in the current syntax table. */ + +static Lisp_Object +SYNTAX_MATCH (int c) +{ + Lisp_Object ent = SYNTAX_ENTRY (c); + return CONSP (ent) ? XCDR (ent) : Qnil; +} + +/* This should be called with FROM at the start of forward + search, or after the last position of the backward search. It + makes sure that the first char is picked up with correct table, so + one does not need to call UPDATE_SYNTAX_TABLE immediately after the + call. + Sign of COUNT gives the direction of the search. + */ + +static void +SETUP_SYNTAX_TABLE (ptrdiff_t from, ptrdiff_t count) +{ + SETUP_BUFFER_SYNTAX_TABLE (); + gl_state.b_property = BEGV; + gl_state.e_property = ZV + 1; + gl_state.object = Qnil; + gl_state.offset = 0; + if (parse_sexp_lookup_properties) + if (count > 0 || from > BEGV) + update_syntax_table (count > 0 ? from : from - 1, count, 1, Qnil); +} + +/* Same as above, but in OBJECT. If OBJECT is nil, use current buffer. + If it is t (which is only used in fast_c_string_match_ignore_case), + ignore properties altogether. + + This is meant for regex.c to use. For buffers, regex.c passes arguments + to the UPDATE_SYNTAX_TABLE functions which are relative to BEGV. + So if it is a buffer, we set the offset field to BEGV. */ + +void +SETUP_SYNTAX_TABLE_FOR_OBJECT (Lisp_Object object, + ptrdiff_t from, ptrdiff_t count) +{ + SETUP_BUFFER_SYNTAX_TABLE (); + gl_state.object = object; + if (BUFFERP (gl_state.object)) + { + struct buffer *buf = XBUFFER (gl_state.object); + gl_state.b_property = 1; + gl_state.e_property = BUF_ZV (buf) - BUF_BEGV (buf) + 1; + gl_state.offset = BUF_BEGV (buf) - 1; + } + else if (NILP (gl_state.object)) + { + gl_state.b_property = 1; + gl_state.e_property = ZV - BEGV + 1; + gl_state.offset = BEGV - 1; + } + else if (EQ (gl_state.object, Qt)) + { + gl_state.b_property = 0; + gl_state.e_property = PTRDIFF_MAX; + gl_state.offset = 0; + } + else + { + gl_state.b_property = 0; + gl_state.e_property = 1 + SCHARS (gl_state.object); + gl_state.offset = 0; + } + if (parse_sexp_lookup_properties) + update_syntax_table (from + gl_state.offset - (count <= 0), + count, 1, gl_state.object); +} + /* Update gl_state to an appropriate interval which contains CHARPOS. The sign of COUNT give the relative position of CHARPOS wrt the previously 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, } immediate_quit = 1; - /* This code may look up syntax tables using macros that rely on the + /* This code may look up syntax tables using functions that rely on the gl_state object. To make sure this object is not out of date, let's initialize it manually. We ignore syntax-table text-properties for now, since that's @@ -2426,11 +2553,13 @@ between them, return t; otherwise return nil. */) } /* Return syntax code of character C if C is an ASCII character - or `multibyte_symbol_p' is zero. Otherwise, return Ssymbol. */ + or if MULTIBYTE_SYMBOL_P is false. Otherwise, return Ssymbol. */ -#define SYNTAX_WITH_MULTIBYTE_CHECK(c) \ - ((ASCII_CHAR_P (c) || !multibyte_symbol_p) \ - ? SYNTAX (c) : Ssymbol) +static enum syntaxcode +syntax_multibyte (int c, bool multibyte_symbol_p) +{ + return ASCII_CHAR_P (c) || !multibyte_symbol_p ? SYNTAX (c) : Ssymbol; +} static Lisp_Object scan_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) int stringterm; bool quoted; bool mathexit = 0; - enum syntaxcode code, temp_code, c_code; + enum syntaxcode code; EMACS_INT min_depth = depth; /* Err out if depth gets less than this. */ int comstyle = 0; /* style of comment encountered */ 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) UPDATE_SYNTAX_TABLE_FORWARD (from); c = FETCH_CHAR_AS_MULTIBYTE (from_byte); syntax = SYNTAX_WITH_FLAGS (c); - code = SYNTAX_WITH_MULTIBYTE_CHECK (c); + code = syntax_multibyte (c, multibyte_symbol_p); comstart_first = SYNTAX_FLAGS_COMSTART_FIRST (syntax); comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax); comstyle = SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0); @@ -2519,10 +2648,8 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag) { UPDATE_SYNTAX_TABLE_FORWARD (from); - /* Some compilers can't handle this inside the switch. */ c = FETCH_CHAR_AS_MULTIBYTE (from_byte); - c_code = SYNTAX_WITH_MULTIBYTE_CHECK (c); - switch (c_code) + switch (syntax_multibyte (c, multibyte_symbol_p)) { case Scharquote: case Sescape: @@ -2594,18 +2721,17 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag) stringterm = FETCH_CHAR_AS_MULTIBYTE (temp_pos); while (1) { + enum syntaxcode c_code; if (from >= stop) goto lose; UPDATE_SYNTAX_TABLE_FORWARD (from); c = FETCH_CHAR_AS_MULTIBYTE (from_byte); + c_code = syntax_multibyte (c, multibyte_symbol_p); if (code == Sstring - ? (c == stringterm - && SYNTAX_WITH_MULTIBYTE_CHECK (c) == Sstring) - : SYNTAX_WITH_MULTIBYTE_CHECK (c) == Sstring_fence) + ? c == stringterm && c_code == Sstring + : c_code == Sstring_fence) break; - /* Some compilers can't handle this inside the switch. */ - c_code = SYNTAX_WITH_MULTIBYTE_CHECK (c); switch (c_code) { case Scharquote: @@ -2644,7 +2770,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag) UPDATE_SYNTAX_TABLE_BACKWARD (from); c = FETCH_CHAR_AS_MULTIBYTE (from_byte); syntax= SYNTAX_WITH_FLAGS (c); - code = SYNTAX_WITH_MULTIBYTE_CHECK (c); + code = syntax_multibyte (c, multibyte_symbol_p); if (depth == min_depth) last_good = from; comstyle = 0; @@ -2697,9 +2823,8 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag) temp_pos--; UPDATE_SYNTAX_TABLE_BACKWARD (from - 1); c1 = FETCH_CHAR_AS_MULTIBYTE (temp_pos); - temp_code = SYNTAX_WITH_MULTIBYTE_CHECK (c1); /* Don't allow comment-end to be quoted. */ - if (temp_code == Sendcomment) + if (syntax_multibyte (c1, multibyte_symbol_p) == Sendcomment) goto done2; quoted = char_quoted (from - 1, temp_pos); if (quoted) @@ -2709,11 +2834,12 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag) UPDATE_SYNTAX_TABLE_BACKWARD (from - 1); } c1 = FETCH_CHAR_AS_MULTIBYTE (temp_pos); - temp_code = SYNTAX_WITH_MULTIBYTE_CHECK (c1); - if (! (quoted || temp_code == Sword - || temp_code == Ssymbol - || temp_code == Squote)) - goto done2; + if (! quoted) + switch (syntax_multibyte (c1, multibyte_symbol_p)) + { + case Sword: case Ssymbol: case Squote: break; + default: goto done2; + } DEC_BOTH (from, from_byte); } goto done2; @@ -2768,10 +2894,12 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag) goto lose; DEC_BOTH (from, from_byte); UPDATE_SYNTAX_TABLE_BACKWARD (from); - if (!char_quoted (from, from_byte) - && (c = FETCH_CHAR_AS_MULTIBYTE (from_byte), - SYNTAX_WITH_MULTIBYTE_CHECK (c) == code)) - break; + if (!char_quoted (from, from_byte)) + { + c = FETCH_CHAR_AS_MULTIBYTE (from_byte); + if (syntax_multibyte (c, multibyte_symbol_p) == code) + break; + } } if (code == Sstring_fence && !depth && sexpflag) goto done2; break; @@ -2784,11 +2912,14 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag) goto lose; DEC_BOTH (from, from_byte); UPDATE_SYNTAX_TABLE_BACKWARD (from); - if (!char_quoted (from, from_byte) - && (stringterm - == (c = FETCH_CHAR_AS_MULTIBYTE (from_byte))) - && SYNTAX_WITH_MULTIBYTE_CHECK (c) == Sstring) - break; + if (!char_quoted (from, from_byte)) + { + c = FETCH_CHAR_AS_MULTIBYTE (from_byte); + if (c == stringterm + && (syntax_multibyte (c, multibyte_symbol_p) + == Sstring)) + break; + } } if (!depth && sexpflag) goto done2; break; @@ -2894,7 +3025,7 @@ This includes chars with "quote" or "prefix" syntax (' or p). */) while (!char_quoted (pos, pos_byte) /* Previous statement updates syntax table. */ && ((c = FETCH_CHAR_AS_MULTIBYTE (pos_byte), SYNTAX (c) == Squote) - || SYNTAX_PREFIX (c))) + || syntax_prefix_flag_p (c))) { opoint = pos; opoint_byte = pos_byte; @@ -3117,10 +3248,8 @@ do { prev_from = from; \ symstarted: while (from < end) { - /* Some compilers can't handle this inside the switch. */ int symchar = FETCH_CHAR_AS_MULTIBYTE (from_byte); - enum syntaxcode symcharcode = SYNTAX (symchar); - switch (symcharcode) + switch (SYNTAX (symchar)) { case Scharquote: case Sescape: @@ -3206,7 +3335,6 @@ do { prev_from = from; \ if (from >= end) goto done; c = FETCH_CHAR_AS_MULTIBYTE (from_byte); - /* Some compilers can't handle this inside the switch. */ c_code = SYNTAX (c); /* 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. You should have received a copy of the GNU General Public License along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ +INLINE_HEADER_BEGIN +#ifndef SYNTAX_INLINE +# define SYNTAX_INLINE INLINE +#endif extern void update_syntax_table (ptrdiff_t, EMACS_INT, bool, Lisp_Object); @@ -54,79 +58,64 @@ enum syntaxcode Smax /* Upper bound on codes that are meaningful */ }; -/* Set the syntax entry VAL for char C in table TABLE. */ - -#define SET_RAW_SYNTAX_ENTRY(table, c, val) \ - CHAR_TABLE_SET ((table), c, (val)) -/* Set the syntax entry VAL for char-range RANGE in table TABLE. - RANGE is a cons (FROM . TO) specifying the range of characters. */ +struct gl_state_s +{ + Lisp_Object object; /* The object we are scanning. */ + ptrdiff_t start; /* Where to stop. */ + ptrdiff_t stop; /* Where to stop. */ + bool use_global; /* Whether to use global_code + or c_s_t. */ + Lisp_Object global_code; /* Syntax code of current char. */ + Lisp_Object current_syntax_table; /* Syntax table for current pos. */ + Lisp_Object old_prop; /* Syntax-table prop at prev pos. */ + ptrdiff_t b_property; /* First index where c_s_t is valid. */ + ptrdiff_t e_property; /* First index where c_s_t is + not valid. */ + INTERVAL forward_i; /* Where to start lookup on forward */ + INTERVAL backward_i; /* or backward movement. The + data in c_s_t is valid + between these intervals, + and possibly at the + intervals too, depending + on: */ + /* Offset for positions specified to UPDATE_SYNTAX_TABLE. */ + ptrdiff_t offset; +}; -#define SET_RAW_SYNTAX_ENTRY_RANGE(table, range, val) \ - Fset_char_table_range ((table), (range), (val)) +extern struct gl_state_s gl_state; -/* SYNTAX_ENTRY fetches the information from the entry for character C +/* Fetch the information from the entry for character C in syntax table TABLE, or from globally kept data (gl_state). Does inheritance. */ -/* CURRENT_SYNTAX_TABLE gives the syntax table valid for current - position, it is either the buffer's syntax table, or syntax table - found in text properties. */ +SYNTAX_INLINE Lisp_Object +SYNTAX_ENTRY (int c) +{ #ifdef SYNTAX_ENTRY_VIA_PROPERTY -# define SYNTAX_ENTRY(c) \ - (gl_state.use_global ? gl_state.global_code : SYNTAX_ENTRY_INT (c)) -# define CURRENT_SYNTAX_TABLE gl_state.current_syntax_table + return (gl_state.use_global + ? gl_state.global_code + : CHAR_TABLE_REF (gl_state.current_syntax_table, c)); #else -# define SYNTAX_ENTRY SYNTAX_ENTRY_INT -# define CURRENT_SYNTAX_TABLE BVAR (current_buffer, syntax_table) + return CHAR_TABLE_REF (BVAR (current_buffer, syntax_table), c); #endif - -#define SYNTAX_ENTRY_INT(c) CHAR_TABLE_REF (CURRENT_SYNTAX_TABLE, (c)) +} /* Extract the information from the entry for character C in the current syntax table. */ -#ifdef __GNUC__ -#define SYNTAX(c) \ - ({ Lisp_Object _syntax_temp; \ - _syntax_temp = SYNTAX_ENTRY (c); \ - (CONSP (_syntax_temp) \ - ? (enum syntaxcode) (XINT (XCAR (_syntax_temp)) & 0xff) \ - : Swhitespace); }) - -#define SYNTAX_WITH_FLAGS(c) \ - ({ Lisp_Object _syntax_temp; \ - _syntax_temp = SYNTAX_ENTRY (c); \ - (CONSP (_syntax_temp) \ - ? XINT (XCAR (_syntax_temp)) \ - : Swhitespace); }) - -#define SYNTAX_MATCH(c) \ - ({ Lisp_Object _syntax_temp; \ - _syntax_temp = SYNTAX_ENTRY (c); \ - (CONSP (_syntax_temp) \ - ? XCDR (_syntax_temp) \ - : Qnil); }) -#else -extern Lisp_Object syntax_temp; -#define SYNTAX(c) \ - (syntax_temp = SYNTAX_ENTRY ((c)), \ - (CONSP (syntax_temp) \ - ? (enum syntaxcode) (XINT (XCAR (syntax_temp)) & 0xff) \ - : Swhitespace)) - -#define SYNTAX_WITH_FLAGS(c) \ - (syntax_temp = SYNTAX_ENTRY ((c)), \ - (CONSP (syntax_temp) \ - ? XINT (XCAR (syntax_temp)) \ - : Swhitespace)) - -#define SYNTAX_MATCH(c) \ - (syntax_temp = SYNTAX_ENTRY ((c)), \ - (CONSP (syntax_temp) \ - ? XCDR (syntax_temp) \ - : Qnil)) -#endif +SYNTAX_INLINE int +SYNTAX_WITH_FLAGS (int c) +{ + Lisp_Object ent = SYNTAX_ENTRY (c); + return CONSP (ent) ? XINT (XCAR (ent)) : Swhitespace; +} + +SYNTAX_INLINE enum syntaxcode +SYNTAX (int c) +{ + return SYNTAX_WITH_FLAGS (c) & 0xff; +} /* Whether the syntax of the character C has the prefix flag set. */ @@ -145,158 +134,65 @@ extern char const syntax_code_spec[16]; /* Convert the byte offset BYTEPOS into a character position, for the object recorded in gl_state with SETUP_SYNTAX_TABLE_FOR_OBJECT. - The value is meant for use in the UPDATE_SYNTAX_TABLE... macros. - These macros do nothing when parse_sexp_lookup_properties is 0, - so we return 0 in that case, for speed. */ - -#define SYNTAX_TABLE_BYTE_TO_CHAR(bytepos) \ - (! parse_sexp_lookup_properties \ - ? 0 \ - : STRINGP (gl_state.object) \ - ? string_byte_to_char (gl_state.object, (bytepos)) \ - : BUFFERP (gl_state.object) \ - ? buf_bytepos_to_charpos (XBUFFER (gl_state.object), \ - (bytepos) + BUF_BEGV_BYTE (XBUFFER (gl_state.object)) - 1) - BUF_BEGV (XBUFFER (gl_state.object)) + 1 \ - : NILP (gl_state.object) \ - ? BYTE_TO_CHAR ((bytepos) + BEGV_BYTE - 1) - BEGV + 1 \ - : (bytepos)) + The value is meant for use in code that does nothing when + parse_sexp_lookup_properties is 0, so return 0 in that case, for speed. */ + +SYNTAX_INLINE ptrdiff_t +SYNTAX_TABLE_BYTE_TO_CHAR (ptrdiff_t bytepos) +{ + return (! parse_sexp_lookup_properties + ? 0 + : STRINGP (gl_state.object) + ? string_byte_to_char (gl_state.object, bytepos) + : BUFFERP (gl_state.object) + ? ((buf_bytepos_to_charpos + (XBUFFER (gl_state.object), + (bytepos + BUF_BEGV_BYTE (XBUFFER (gl_state.object)) - 1))) + - BUF_BEGV (XBUFFER (gl_state.object)) + 1) + : NILP (gl_state.object) + ? BYTE_TO_CHAR (bytepos + BEGV_BYTE - 1) - BEGV + 1 + : bytepos); +} /* Make syntax table state (gl_state) good for CHARPOS, assuming it is currently good for a position before CHARPOS. */ -#define UPDATE_SYNTAX_TABLE_FORWARD(charpos) \ - (parse_sexp_lookup_properties \ - && (charpos) >= gl_state.e_property \ - ? (update_syntax_table ((charpos) + gl_state.offset, 1, 0, \ - gl_state.object), \ - 1) \ - : 0) +SYNTAX_INLINE void +UPDATE_SYNTAX_TABLE_FORWARD (ptrdiff_t charpos) +{ + if (parse_sexp_lookup_properties && charpos >= gl_state.e_property) + update_syntax_table (charpos + gl_state.offset, 1, 0, gl_state.object); +} /* Make syntax table state (gl_state) good for CHARPOS, assuming it is currently good for a position after CHARPOS. */ -#define UPDATE_SYNTAX_TABLE_BACKWARD(charpos) \ - (parse_sexp_lookup_properties \ - && (charpos) < gl_state.b_property \ - ? (update_syntax_table ((charpos) + gl_state.offset, -1, 0, \ - gl_state.object), \ - 1) \ - : 0) +SYNTAX_INLINE void +UPDATE_SYNTAX_TABLE_BACKWARD (ptrdiff_t charpos) +{ + if (parse_sexp_lookup_properties && charpos < gl_state.b_property) + update_syntax_table (charpos + gl_state.offset, -1, 0, gl_state.object); +} /* Make syntax table good for CHARPOS. */ -#define UPDATE_SYNTAX_TABLE(charpos) \ - (parse_sexp_lookup_properties \ - && (charpos) < gl_state.b_property \ - ? (update_syntax_table ((charpos) + gl_state.offset, -1, 0, \ - gl_state.object), \ - 1) \ - : (parse_sexp_lookup_properties \ - && (charpos) >= gl_state.e_property \ - ? (update_syntax_table ((charpos) + gl_state.offset, 1, 0,\ - gl_state.object), \ - 1) \ - : 0)) - -/* This macro sets up the buffer-global syntax table. */ -#define SETUP_BUFFER_SYNTAX_TABLE() \ -do \ - { \ - gl_state.use_global = 0; \ - gl_state.current_syntax_table = BVAR (current_buffer, syntax_table);\ - } while (0) - -/* This macro should be called with FROM at the start of forward - search, or after the last position of the backward search. It - makes sure that the first char is picked up with correct table, so - one does not need to call UPDATE_SYNTAX_TABLE immediately after the - call. - Sign of COUNT gives the direction of the search. - */ - -#define SETUP_SYNTAX_TABLE(FROM, COUNT) \ -do \ - { \ - SETUP_BUFFER_SYNTAX_TABLE (); \ - gl_state.b_property = BEGV; \ - gl_state.e_property = ZV + 1; \ - gl_state.object = Qnil; \ - gl_state.offset = 0; \ - if (parse_sexp_lookup_properties) \ - if ((COUNT) > 0 || (FROM) > BEGV) \ - update_syntax_table ((COUNT) > 0 ? (FROM) : (FROM) - 1, (COUNT),\ - 1, Qnil); \ - } \ -while (0) - -/* Same as above, but in OBJECT. If OBJECT is nil, use current buffer. - If it is t (which is only used in fast_c_string_match_ignore_case), - ignore properties altogether. - - This is meant for regex.c to use. For buffers, regex.c passes arguments - to the UPDATE_SYNTAX_TABLE macros which are relative to BEGV. - So if it is a buffer, we set the offset field to BEGV. */ - -#define SETUP_SYNTAX_TABLE_FOR_OBJECT(OBJECT, FROM, COUNT) \ -do \ - { \ - SETUP_BUFFER_SYNTAX_TABLE (); \ - gl_state.object = (OBJECT); \ - if (BUFFERP (gl_state.object)) \ - { \ - struct buffer *buf = XBUFFER (gl_state.object); \ - gl_state.b_property = 1; \ - gl_state.e_property = BUF_ZV (buf) - BUF_BEGV (buf) + 1; \ - gl_state.offset = BUF_BEGV (buf) - 1; \ - } \ - else if (NILP (gl_state.object)) \ - { \ - gl_state.b_property = 1; \ - gl_state.e_property = ZV - BEGV + 1; \ - gl_state.offset = BEGV - 1; \ - } \ - else if (EQ (gl_state.object, Qt)) \ - { \ - gl_state.b_property = 0; \ - gl_state.e_property = PTRDIFF_MAX; \ - gl_state.offset = 0; \ - } \ - else \ - { \ - gl_state.b_property = 0; \ - gl_state.e_property = 1 + SCHARS (gl_state.object); \ - gl_state.offset = 0; \ - } \ - if (parse_sexp_lookup_properties) \ - update_syntax_table (((FROM) + gl_state.offset \ - + (COUNT > 0 ? 0 : -1)), \ - COUNT, 1, gl_state.object); \ - } \ -while (0) +SYNTAX_INLINE void +UPDATE_SYNTAX_TABLE (ptrdiff_t charpos) +{ + UPDATE_SYNTAX_TABLE_BACKWARD (charpos); + UPDATE_SYNTAX_TABLE_FORWARD (charpos); +} + +/* Set up the buffer-global syntax table. */ -struct gl_state_s +SYNTAX_INLINE void +SETUP_BUFFER_SYNTAX_TABLE (void) { - Lisp_Object object; /* The object we are scanning. */ - ptrdiff_t start; /* Where to stop. */ - ptrdiff_t stop; /* Where to stop. */ - int use_global; /* Whether to use global_code - or c_s_t. */ - Lisp_Object global_code; /* Syntax code of current char. */ - Lisp_Object current_syntax_table; /* Syntax table for current pos. */ - Lisp_Object old_prop; /* Syntax-table prop at prev pos. */ - ptrdiff_t b_property; /* First index where c_s_t is valid. */ - ptrdiff_t e_property; /* First index where c_s_t is - not valid. */ - INTERVAL forward_i; /* Where to start lookup on forward */ - INTERVAL backward_i; /* or backward movement. The - data in c_s_t is valid - between these intervals, - and possibly at the - intervals too, depending - on: */ - /* Offset for positions specified to UPDATE_SYNTAX_TABLE. */ - ptrdiff_t offset; -}; + gl_state.use_global = 0; + gl_state.current_syntax_table = BVAR (current_buffer, syntax_table); +} -extern struct gl_state_s gl_state; extern ptrdiff_t scan_words (ptrdiff_t, EMACS_INT); +extern void SETUP_SYNTAX_TABLE_FOR_OBJECT (Lisp_Object, ptrdiff_t, ptrdiff_t); + +INLINE_HEADER_END diff --git a/src/sysdep.c b/src/sysdep.c index 91e941a2050..f614d8bc557 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -31,7 +31,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <unistd.h> #include <c-ctype.h> -#include <ignore-value.h> #include <utimens.h> #include "lisp.h" @@ -103,8 +102,8 @@ int _cdecl _getpid (void); #include "syssignal.h" #include "systime.h" -static int emacs_get_tty (int, struct emacs_tty *); -static int emacs_set_tty (int, struct emacs_tty *, int); +static void emacs_get_tty (int, struct emacs_tty *); +static int emacs_set_tty (int, struct emacs_tty *, bool); /* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781. */ #ifndef ULLONG_MAX @@ -538,13 +537,11 @@ sys_subshell (void) if (str && chdir ((char *) str) != 0) { #ifndef DOS_NT - ignore_value (write (1, "Can't chdir\n", 12)); - _exit (1); + emacs_perror ((char *) str); + _exit (EXIT_CANCELED); #endif } - close_process_descs (); /* Close Emacs's pipes/ptys */ - #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */ { char *epwd = getenv ("PWD"); @@ -572,8 +569,8 @@ sys_subshell (void) write (1, "Can't execute subshell", 22); #else /* not WINDOWSNT */ execlp (sh, sh, (char *) 0); - ignore_value (write (1, "Can't execute subshell", 22)); - _exit (1); + emacs_perror (sh); + _exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE); #endif /* not WINDOWSNT */ #endif /* not MSDOS */ } @@ -772,31 +769,26 @@ widen_foreground_group (int fd) /* Getting and setting emacs_tty structures. */ -/* Set *TC to the parameters associated with the terminal FD. - Return zero if all's well, or -1 if we ran into an error we - couldn't deal with. */ -int +/* Set *TC to the parameters associated with the terminal FD, + or clear it if the parameters are not available. */ +static void emacs_get_tty (int fd, struct emacs_tty *settings) { /* Retrieve the primary parameters - baud rate, character size, etcetera. */ #ifndef DOS_NT /* We have those nifty POSIX tcmumbleattr functions. */ memset (&settings->main, 0, sizeof (settings->main)); - if (tcgetattr (fd, &settings->main) < 0) - return -1; + tcgetattr (fd, &settings->main); #endif - - /* We have survived the tempest. */ - return 0; } /* Set the parameters of the tty on FD according to the contents of - *SETTINGS. If FLUSHP is non-zero, we discard input. - Return 0 if all went well, and -1 if anything failed. */ + *SETTINGS. If FLUSHP, discard input. + Return 0 if all went well, and -1 (setting errno) if anything failed. */ -int -emacs_set_tty (int fd, struct emacs_tty *settings, int flushp) +static int +emacs_set_tty (int fd, struct emacs_tty *settings, bool flushp) { /* Set the primary parameters - baud rate, character size, etcetera. */ #ifndef DOS_NT @@ -1121,10 +1113,10 @@ init_sys_modes (struct tty_display_info *tty_out) tty_out->term_initted = 1; } -/* Return nonzero if safe to use tabs in output. +/* Return true if safe to use tabs in output. At the time this is called, init_sys_modes has not been done yet. */ -int +bool tabs_safe_p (int fd) { struct emacs_tty etty; @@ -1378,8 +1370,10 @@ init_system_name (void) uname (&uts); Vsystem_name = build_string (uts.nodename); #else /* HAVE_GETHOSTNAME */ - unsigned int hostname_size = 256; - char *hostname = alloca (hostname_size); + char *hostname_alloc = NULL; + char hostname_buf[256]; + ptrdiff_t hostname_size = sizeof hostname_buf; + char *hostname = hostname_buf; /* Try to get the host name; if the buffer is too short, try again. Apparently, the only indication gethostname gives of @@ -1394,8 +1388,8 @@ init_system_name (void) if (strlen (hostname) < hostname_size - 1) break; - hostname_size <<= 1; - hostname = alloca (hostname_size); + hostname = hostname_alloc = xpalloc (hostname_alloc, &hostname_size, 1, + min (PTRDIFF_MAX, SIZE_MAX), 1); } #ifdef HAVE_SOCKETS /* Turn the hostname into the official, fully-qualified hostname. @@ -1440,7 +1434,13 @@ init_system_name (void) } if (it) { - hostname = alloca (strlen (it->ai_canonname) + 1); + ptrdiff_t len = strlen (it->ai_canonname); + if (hostname_size <= len) + { + hostname_size = len + 1; + hostname = hostname_alloc = xrealloc (hostname_alloc, + hostname_size); + } strcpy (hostname, it->ai_canonname); } freeaddrinfo (res); @@ -1487,10 +1487,11 @@ init_system_name (void) } #endif /* HAVE_SOCKETS */ Vsystem_name = build_string (hostname); + xfree (hostname_alloc); #endif /* HAVE_GETHOSTNAME */ { - unsigned char *p; - for (p = SDATA (Vsystem_name); *p; p++) + char *p; + for (p = SSDATA (Vsystem_name); *p; p++) if (*p == ' ' || *p == '\t') *p = '-'; } @@ -2136,10 +2137,10 @@ emacs_backtrace (int backtrace_limit) if (npointers) { - ignore_value (write (STDERR_FILENO, "\nBacktrace:\n", 12)); + emacs_write (STDERR_FILENO, "\nBacktrace:\n", 12); backtrace_symbols_fd (buffer, npointers, STDERR_FILENO); if (bounded_limit < npointers) - ignore_value (write (STDERR_FILENO, "...\n", 4)); + emacs_write (STDERR_FILENO, "...\n", 4); } } @@ -2152,6 +2153,8 @@ emacs_abort (void) #endif /* Open FILE for Emacs use, using open flags OFLAG and mode MODE. + Arrange for subprograms to not inherit the file descriptor. + Prefer a method that is multithread-safe, if available. Do not fail merely because the open was interrupted by a signal. Allow the user to quit. */ @@ -2159,8 +2162,11 @@ int emacs_open (const char *file, int oflags, int mode) { int fd; + oflags |= O_CLOEXEC; while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR) QUIT; + if (! O_CLOEXEC && 0 <= fd) + fcntl (fd, F_SETFD, FD_CLOEXEC); return fd; } @@ -2170,29 +2176,84 @@ emacs_open (const char *file, int oflags, int mode) FILE * emacs_fopen (char const *file, char const *mode) { - FILE *fp; - while (! (fp = fopen (file, mode)) && errno == EINTR) - QUIT; - return fp; + int fd, omode, oflags; + int bflag = 0; + char const *m = mode; + + switch (*m++) + { + case 'r': omode = O_RDONLY; oflags = 0; break; + case 'w': omode = O_WRONLY; oflags = O_CREAT | O_TRUNC; break; + case 'a': omode = O_WRONLY; oflags = O_CREAT | O_APPEND; break; + default: emacs_abort (); + } + + while (*m) + switch (*m++) + { + case '+': omode = O_RDWR; break; + case 'b': bflag = O_BINARY; break; + case 't': bflag = O_TEXT; break; + default: /* Ignore. */ break; + } + + fd = emacs_open (file, omode | oflags | bflag, 0666); + return fd < 0 ? 0 : fdopen (fd, mode); } -int -emacs_close (int fd) +/* Approximate posix_close and POSIX_CLOSE_RESTART well enough for Emacs. + For the background behind this mess, please see Austin Group defect 529 + <http://austingroupbugs.net/view.php?id=529>. */ + +#ifndef POSIX_CLOSE_RESTART +# define POSIX_CLOSE_RESTART 1 +static int +posix_close (int fd, int flag) { - int did_retry = 0; - register int rtnval; + /* Only the POSIX_CLOSE_RESTART case is emulated. */ + eassert (flag == POSIX_CLOSE_RESTART); - while ((rtnval = close (fd)) == -1 - && (errno == EINTR)) - did_retry = 1; + /* Things are tricky if close (fd) returns -1 with errno == EINTR + on a system that does not define POSIX_CLOSE_RESTART. - /* If close is interrupted SunOS 4.1 may or may not have closed the - file descriptor. If it did the second close will fail with - errno = EBADF. That means we have succeeded. */ - if (rtnval == -1 && did_retry && errno == EBADF) - return 0; + In this case, in some systems (e.g., GNU/Linux, AIX) FD is + closed, and retrying the close could inadvertently close a file + descriptor allocated by some other thread. In other systems + (e.g., HP/UX) FD is not closed. And in still other systems + (e.g., OS X, Solaris), maybe FD is closed, maybe not, and in a + multithreaded program there can be no way to tell. - return rtnval; + So, in this case, pretend that the close succeeded. This works + well on systems like GNU/Linux that close FD. Although it may + leak a file descriptor on other systems, the leak is unlikely and + it's better to leak than to close a random victim. */ + return close (fd) == 0 || errno == EINTR ? 0 : -1; +} +#endif + +/* Close FD, retrying if interrupted. If successful, return 0; + otherwise, return -1 and set errno to a non-EINTR value. Consider + an EINPROGRESS error to be successful, as that's merely a signal + arriving. FD is always closed when this function returns, even + when it returns -1. + + Do not call this function if FD is nonnegative and might already be closed, + as that might close an innocent victim opened by some other thread. */ + +int +emacs_close (int fd) +{ + while (1) + { + int r = posix_close (fd, POSIX_CLOSE_RESTART); + if (r == 0) + return r; + if (!POSIX_CLOSE_RESTART || errno != EINTR) + { + eassert (errno != EBADF || fd < 0); + return errno == EINPROGRESS ? 0 : r; + } + } } /* Maximum number of bytes to read or write in a single system call. @@ -2224,27 +2285,26 @@ emacs_read (int fildes, char *buf, ptrdiff_t nbyte) } /* Write to FILEDES from a buffer BUF with size NBYTE, retrying if interrupted - or if a partial write occurs. Return the number of bytes written, setting + or if a partial write occurs. If interrupted, process pending + signals if PROCESS SIGNALS. Return the number of bytes written, setting errno if this is less than NBYTE. */ -ptrdiff_t -emacs_write (int fildes, const char *buf, ptrdiff_t nbyte) +static ptrdiff_t +emacs_full_write (int fildes, char const *buf, ptrdiff_t nbyte, + bool process_signals) { - ssize_t rtnval; - ptrdiff_t bytes_written; - - bytes_written = 0; + ptrdiff_t bytes_written = 0; while (nbyte > 0) { - rtnval = write (fildes, buf, min (nbyte, MAX_RW_COUNT)); + ssize_t n = write (fildes, buf, min (nbyte, MAX_RW_COUNT)); - if (rtnval < 0) + if (n < 0) { if (errno == EINTR) { /* I originally used `QUIT' but that might causes files to be truncated if you hit C-g in the middle of it. --Stef */ - if (pending_signals) + if (process_signals && pending_signals) process_pending_signals (); continue; } @@ -2252,12 +2312,57 @@ emacs_write (int fildes, const char *buf, ptrdiff_t nbyte) break; } - buf += rtnval; - nbyte -= rtnval; - bytes_written += rtnval; + buf += n; + nbyte -= n; + bytes_written += n; } - return (bytes_written); + return bytes_written; +} + +/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if + interrupted or if a partial write occurs. Return the number of + bytes written, setting errno if this is less than NBYTE. */ +ptrdiff_t +emacs_write (int fildes, char const *buf, ptrdiff_t nbyte) +{ + return emacs_full_write (fildes, buf, nbyte, 0); +} + +/* Like emacs_write, but also process pending signals if interrupted. */ +ptrdiff_t +emacs_write_sig (int fildes, char const *buf, ptrdiff_t nbyte) +{ + return emacs_full_write (fildes, buf, nbyte, 1); +} + +/* Write a diagnostic to standard error that contains MESSAGE and a + string derived from errno. Preserve errno. Do not buffer stderr. + Do not process pending signals if interrupted. */ +void +emacs_perror (char const *message) +{ + int err = errno; + char const *error_string = strerror (err); + char const *command = (initial_argv && initial_argv[0] + ? initial_argv[0] : "emacs"); + /* Write it out all at once, if it's short; this is less likely to + be interleaved with other output. */ + char buf[BUFSIZ]; + int nbytes = snprintf (buf, sizeof buf, "%s: %s: %s\n", + command, message, error_string); + if (0 <= nbytes && nbytes < BUFSIZ) + emacs_write (STDERR_FILENO, buf, nbytes); + else + { + emacs_write (STDERR_FILENO, command, strlen (command)); + emacs_write (STDERR_FILENO, ": ", 2); + emacs_write (STDERR_FILENO, message, strlen (message)); + emacs_write (STDERR_FILENO, ": ", 2); + emacs_write (STDERR_FILENO, error_string, strlen (error_string)); + emacs_write (STDERR_FILENO, "\n", 1); + } + errno = err; } /* Return a struct timeval that is roughly equivalent to T. @@ -2611,7 +2716,7 @@ list_system_processes (void) #endif /* !defined (WINDOWSNT) */ -#ifdef GNU_LINUX +#if defined GNU_LINUX && defined HAVE_LONG_LONG_INT static EMACS_TIME time_from_jiffies (unsigned long long tval, long hz) { diff --git a/src/systime.h b/src/systime.h index 0e611a3f5e3..657f2cca11f 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; } SYSTIME_INLINE EMACS_TIME make_emacs_time (time_t s, int ns) { - EMACS_TIME r = { s, ns }; + EMACS_TIME r; + r.tv_sec = s; + r.tv_nsec = ns; return r; } @@ -75,7 +77,9 @@ make_emacs_time (time_t s, int ns) SYSTIME_INLINE EMACS_TIME invalid_emacs_time (void) { - EMACS_TIME r = { 0, -1 }; + EMACS_TIME r; + r.tv_sec = 0; + r.tv_nsec = -1; return r; } @@ -166,21 +170,6 @@ EMACS_TIME_EQ (EMACS_TIME t1, EMACS_TIME t2) return timespec_cmp (t1, t2) == 0; } SYSTIME_INLINE int -EMACS_TIME_NE (EMACS_TIME t1, EMACS_TIME t2) -{ - return timespec_cmp (t1, t2) != 0; -} -SYSTIME_INLINE int -EMACS_TIME_GT (EMACS_TIME t1, EMACS_TIME t2) -{ - return timespec_cmp (t1, t2) > 0; -} -SYSTIME_INLINE int -EMACS_TIME_GE (EMACS_TIME t1, EMACS_TIME t2) -{ - return timespec_cmp (t1, t2) >= 0; -} -SYSTIME_INLINE int EMACS_TIME_LT (EMACS_TIME t1, EMACS_TIME t2) { return timespec_cmp (t1, t2) < 0; diff --git a/src/term.c b/src/term.c index 39d143564c6..b6878a0abd1 100644 --- a/src/term.c +++ b/src/term.c @@ -71,13 +71,13 @@ static void tty_turn_off_highlight (struct tty_display_info *); static void tty_show_cursor (struct tty_display_info *); static void tty_hide_cursor (struct tty_display_info *); static void tty_background_highlight (struct tty_display_info *tty); -static struct terminal *get_tty_terminal (Lisp_Object, int); +static struct terminal *get_tty_terminal (Lisp_Object, bool); static void clear_tty_hooks (struct terminal *terminal); static void set_tty_hooks (struct terminal *terminal); static void dissociate_if_controlling_tty (int fd); static void delete_tty (struct terminal *); -static _Noreturn void maybe_fatal (int must_succeed, struct terminal *terminal, - const char *str1, const char *str2, ...) +static _Noreturn void maybe_fatal (bool, struct terminal *, + const char *, const char *, ...) ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5); static _Noreturn void vfatal (const char *str, va_list ap) ATTRIBUTE_FORMAT_PRINTF (1, 0); @@ -85,8 +85,7 @@ static _Noreturn void vfatal (const char *str, va_list ap) #define OUTPUT(tty, a) \ emacs_tputs ((tty), a, \ - (int) (FRAME_LINES (XFRAME (selected_frame)) \ - - curY (tty)), \ + FRAME_LINES (XFRAME (selected_frame)) - curY (tty), \ cmputc) #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) { unsigned char *conversion_buffer; struct coding_system *coding; - size_t n, stringlen; + int n, stringlen; struct tty_display_info *tty = FRAME_TTY (f); @@ -1431,7 +1430,7 @@ static void append_glyph (struct it *); static void append_composite_glyph (struct it *); static void produce_composite_glyph (struct it *); static void append_glyphless_glyph (struct it *, int, const char *); -static void produce_glyphless_glyph (struct it *, int, Lisp_Object); +static void produce_glyphless_glyph (struct it *, Lisp_Object); /* Append glyphs to IT's glyph_row. Called from produce_glyphs for terminal frames if IT->glyph_row != NULL. IT->char_to_display is @@ -1551,7 +1550,7 @@ produce_glyphs (struct it *it) if (it->what == IT_GLYPHLESS) { - produce_glyphless_glyph (it, 0, Qnil); + produce_glyphless_glyph (it, Qnil); goto done; } @@ -1620,7 +1619,7 @@ produce_glyphs (struct it *it) Lisp_Object acronym = lookup_glyphless_char_display (-1, it); eassert (it->what == IT_GLYPHLESS); - produce_glyphless_glyph (it, 1, acronym); + produce_glyphless_glyph (it, acronym); } } @@ -1794,14 +1793,12 @@ append_glyphless_glyph (struct it *it, int face_id, const char *str) the character. See the description of enum glyphless_display_method in dispextern.h for the details. - FOR_NO_FONT is nonzero if and only if this is for a character that - is not supported by the coding system of the terminal. ACRONYM, if - non-nil, is an acronym string for the character. + ACRONYM, if non-nil, is an acronym string for the character. The glyphs actually produced are of type CHAR_GLYPH. */ static void -produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) +produce_glyphless_glyph (struct it *it, Lisp_Object acronym) { int face_id; int len; @@ -1968,7 +1965,7 @@ turn_on_face (struct frame *f, int face_id) ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground; if (fg >= 0 && ts) { - p = tparam (ts, NULL, 0, (int) fg, 0, 0, 0); + p = tparam (ts, NULL, 0, fg, 0, 0, 0); OUTPUT (tty, p); xfree (p); } @@ -1976,7 +1973,7 @@ turn_on_face (struct frame *f, int face_id) ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background; if (bg >= 0 && ts) { - p = tparam (ts, NULL, 0, (int) bg, 0, 0, 0); + p = tparam (ts, NULL, 0, bg, 0, 0, 0); OUTPUT (tty, p); xfree (p); } @@ -2027,11 +2024,11 @@ turn_off_face (struct frame *f, int face_id) } -/* Return non-zero if the terminal on frame F supports all of the +/* Return true if the terminal on frame F supports all of the capabilities in CAPS simultaneously, with foreground and background colors FG and BG. */ -int +bool tty_capable_p (struct tty_display_info *tty, unsigned int caps, unsigned long fg, unsigned long bg) { @@ -2099,7 +2096,7 @@ static char *default_set_background; /* Save or restore the default color-related capabilities of this terminal. */ static void -tty_default_color_capabilities (struct tty_display_info *tty, int save) +tty_default_color_capabilities (struct tty_display_info *tty, bool save) { if (save) @@ -2209,7 +2206,7 @@ set_tty_color_mode (struct tty_display_info *tty, struct frame *f) /* Return the tty display object specified by TERMINAL. */ static struct terminal * -get_tty_terminal (Lisp_Object terminal, int throw) +get_tty_terminal (Lisp_Object terminal, bool throw) { struct terminal *t = get_terminal (terminal, throw); @@ -2481,7 +2478,7 @@ term_mouse_moveto (int x, int y) name = (const char *) ttyname (0); fd = emacs_open (name, O_WRONLY, 0); SOME_FUNCTION (x, y, fd); - close (fd); + emacs_close (fd); last_mouse_x = x; last_mouse_y = y; */ } @@ -2519,7 +2516,7 @@ tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row, cursor_to (f, save_y, save_x); } -static int +static bool term_mouse_movement (FRAME_PTR frame, Gpm_Event *event) { /* 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 { struct frame *f = XFRAME (tty->top_frame); struct input_event ie; - int do_help = 0; + bool do_help = 0; int count = 0; EVENT_INIT (ie); @@ -2934,7 +2931,7 @@ dissociate_if_controlling_tty (int fd) If MUST_SUCCEED is true, then all errors are fatal. */ struct terminal * -init_tty (const char *name, const char *terminal_type, int must_succeed) +init_tty (const char *name, const char *terminal_type, bool must_succeed) { char *area = NULL; char **address = &area; @@ -2942,7 +2939,7 @@ init_tty (const char *name, const char *terminal_type, int must_succeed) int status; struct tty_display_info *tty = NULL; struct terminal *terminal = NULL; - int ctty = 0; /* 1 if asked to open controlling tty. */ + bool ctty = 0; /* True if asked to open controlling tty. */ if (!terminal_type) maybe_fatal (must_succeed, 0, @@ -3015,7 +3012,7 @@ init_tty (const char *name, const char *terminal_type, int must_succeed) name); if (!isatty (fd)) { - close (fd); + emacs_close (fd); maybe_fatal (must_succeed, terminal, "Not a tty device: %s", "Not a tty device: %s", @@ -3412,10 +3409,10 @@ vfatal (const char *str, va_list ap) /* Auxiliary error-handling function for init_tty. Delete TERMINAL, then call error or fatal with str1 or str2, - respectively, according to whether MUST_SUCCEED is zero or not. */ + respectively, according to whether MUST_SUCCEED is true. */ static void -maybe_fatal (int must_succeed, struct terminal *terminal, +maybe_fatal (bool must_succeed, struct terminal *terminal, const char *str1, const char *str2, ...) { va_list ap; diff --git a/src/termcap.c b/src/termcap.c index 7256eef9e81..be05828eea6 100644 --- a/src/termcap.c +++ b/src/termcap.c @@ -213,8 +213,8 @@ tgetst1 (char *ptr, char **area) abbreviation expansion makes that effort a little more hairy than its worth; this is cleaner. */ { - register int last_p_param = 0; - int remove_p_params = 1; + int last_p_param = 0; + bool remove_p_params = 1; struct { char *beg; int len; } cut[11]; for (cut[0].beg = p = ret; p < r - 3; p++) @@ -318,26 +318,26 @@ struct termcap_buffer char *beg; ptrdiff_t size; char *ptr; - int ateof; + bool ateof; ptrdiff_t full; }; /* Forward declarations of static functions. */ -static int scan_file (char *str, int fd, register struct termcap_buffer *bufp); -static char *gobble_line (int fd, register struct termcap_buffer *bufp, char *append_end); -static int compare_contin (register char *str1, register char *str2); -static int name_match (char *line, char *name); +static bool scan_file (char *, int, struct termcap_buffer *); +static char *gobble_line (int, struct termcap_buffer *, char *); +static bool compare_contin (char *, char *); +static bool name_match (char *, char *); -#ifdef MSDOS /* MW, May 1993 */ -static int +static bool valid_filename_p (char *fn) { +#ifdef MSDOS return *fn == '/' || fn[1] == ':'; -} #else -#define valid_filename_p(fn) (*(fn) == '/') + return *fn == '/'; #endif +} /* Find the termcap entry data for terminal type NAME and store it in the block that BP points to. @@ -360,10 +360,10 @@ tgetent (char *bp, const char *name) char *tc_search_point; char *term; ptrdiff_t malloc_size = 0; - register int c; + int c; char *tcenv = NULL; /* TERMCAP value, if it contains :tc=. */ char *indirect = NULL; /* Terminal type in :tc= in TERMCAP value. */ - int filep; + bool filep; #ifdef INTERNAL_TERMINAL /* For the internal terminal we don't want to read any termcap file, @@ -455,7 +455,7 @@ tgetent (char *bp, const char *name) /* Scan the file, reading it via buf, till find start of main entry. */ if (scan_file (term, fd, &buf) == 0) { - close (fd); + emacs_close (fd); xfree (buf.beg); if (malloc_size) xfree (bp); @@ -493,7 +493,7 @@ tgetent (char *bp, const char *name) term = tgetst1 (tc_search_point, (char **) 0); } - close (fd); + emacs_close (fd); xfree (buf.beg); if (malloc_size) @@ -510,10 +510,10 @@ tgetent (char *bp, const char *name) Return 1 if successful, with that line in BUFP, or 0 if no entry is found in the file. */ -static int -scan_file (char *str, int fd, register struct termcap_buffer *bufp) +static bool +scan_file (char *str, int fd, struct termcap_buffer *bufp) { - register char *end; + char *end; bufp->ptr = bufp->beg; bufp->full = 0; @@ -544,13 +544,13 @@ scan_file (char *str, int fd, register struct termcap_buffer *bufp) return 0; } -/* Return nonzero if NAME is one of the names specified +/* Return true if NAME is one of the names specified by termcap entry LINE. */ -static int +static bool name_match (char *line, char *name) { - register char *tem; + char *tem; if (!compare_contin (line, name)) return 1; @@ -562,18 +562,18 @@ name_match (char *line, char *name) return 0; } -static int -compare_contin (register char *str1, register char *str2) +static bool +compare_contin (char *str1, char *str2) { - register int c1, c2; while (1) { - c1 = *str1++; - c2 = *str2++; + int c1 = *str1++; + int c2 = *str2++; while (c1 == '\\' && *str1 == '\n') { str1++; - while ((c1 = *str1++) == ' ' || c1 == '\t'); + while ((c1 = *str1++) == ' ' || c1 == '\t') + continue; } if (c2 == '\0') { @@ -647,57 +647,3 @@ gobble_line (int fd, register struct termcap_buffer *bufp, char *append_end) } return end + 1; } - -#ifdef TEST - -#include <stdio.h> - -static void -tprint (char *cap) -{ - char *x = tgetstr (cap, 0); - register char *y; - - printf ("%s: ", cap); - if (x) - { - for (y = x; *y; y++) - if (*y <= ' ' || *y == 0177) - printf ("\\%0o", *y); - else - putchar (*y); - free (x); - } - else - printf ("none"); - putchar ('\n'); -} - -int -main (int argc, char **argv) -{ - char *term; - char *buf; - - term = argv[1]; - printf ("TERM: %s\n", term); - - buf = (char *) tgetent (0, term); - if ((int) buf <= 0) - { - printf ("No entry.\n"); - return 0; - } - - printf ("Entry: %s\n", buf); - - tprint ("cm"); - tprint ("AL"); - - printf ("co: %d\n", tgetnum ("co")); - printf ("am: %d\n", tgetflag ("am")); - - return 0; -} - -#endif /* TEST */ diff --git a/src/termhooks.h b/src/termhooks.h index 4f3fa9cb47f..0190478c254 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -643,7 +643,7 @@ extern struct terminal *terminal_list; (((d)->type != output_termcap && (d)->type != output_msdos_raw) \ || (d)->display_info.tty->input) -extern struct terminal *get_terminal (Lisp_Object terminal, int); +extern struct terminal *get_terminal (Lisp_Object terminal, bool); extern struct terminal *create_terminal (void); extern void delete_terminal (struct terminal *); 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) /* Return the terminal object specified by TERMINAL. TERMINAL may be a terminal object, a frame, or nil for the terminal device of the - current frame. If THROW is zero, return NULL for failure, + current frame. If THROW is false, return NULL for failure, otherwise throw an error. */ struct terminal * -get_terminal (Lisp_Object terminal, int throw) +get_terminal (Lisp_Object terminal, bool throw) { struct terminal *result = NULL; 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) if (base_buffer->base_buffer) base_buffer = base_buffer->base_buffer; - bset_undo_list - (current_buffer, - Fcons (Fcons (Qt, make_lisp_time (base_buffer->modtime)), - BVAR (current_buffer, undo_list))); + bset_undo_list (current_buffer, + Fcons (Fcons (Qt, Fvisited_file_modtime ()), + BVAR (current_buffer, undo_list))); } /* Record a change in property PROP (whose old value was VAL) diff --git a/src/unexaix.c b/src/unexaix.c index 204f6cf4ad3..757ba6f51b3 100644 --- a/src/unexaix.c +++ b/src/unexaix.c @@ -94,13 +94,10 @@ static int pagemask; static _Noreturn void report_error (const char *file, int fd) { + int err = errno; if (fd) - { - int failed_errno = errno; - close (fd); - errno = failed_errno; - } - report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil)); + emacs_close (fd); + report_file_errno ("Cannot unexec", Fcons (build_string (file), Qnil), err); } #define ERROR0(msg) report_error_1 (new, msg) @@ -111,7 +108,7 @@ static _Noreturn void ATTRIBUTE_FORMAT_PRINTF (2, 3) report_error_1 (int fd, const char *msg, ...) { va_list ap; - close (fd); + emacs_close (fd); va_start (ap, msg); verror (msg, ap); va_end (ap); @@ -148,13 +145,13 @@ unexec (const char *new_name, const char *a_name) || adjust_lnnoptrs (new, a_out, new_name) < 0 || unrelocate_symbols (new, a_out, a_name, new_name) < 0) { - close (new); + emacs_close (new); return; } - close (new); + emacs_close (new); if (a_out >= 0) - close (a_out); + emacs_close (a_out); mark_x (new_name); } @@ -534,7 +531,7 @@ adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name) } } } - close (new); + emacs_close (new); return 0; } diff --git a/src/unexcoff.c b/src/unexcoff.c index e79821251ba..c467e59a665 100644 --- a/src/unexcoff.c +++ b/src/unexcoff.c @@ -127,9 +127,10 @@ static int pagemask; static void report_error (const char *file, int fd) { + int err = errno; if (fd) - close (fd); - report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil)); + emacs_close (fd); + report_file_errno ("Cannot unexec", Fcons (build_string (file), Qnil), err); } #define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1 @@ -139,7 +140,7 @@ report_error (const char *file, int fd) static void report_error_1 (int fd, const char *msg, int a1, int a2) { - close (fd); + emacs_close (fd); error (msg, a1, a2); } @@ -511,7 +512,7 @@ adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name) } } #ifndef MSDOS - close (new); + emacs_close (new); #endif return 0; } @@ -541,13 +542,13 @@ unexec (const char *new_name, const char *a_name) || adjust_lnnoptrs (new, a_out, new_name) < 0 ) { - close (new); + emacs_close (new); return; } - close (new); + emacs_close (new); if (a_out >= 0) - close (a_out); + emacs_close (a_out); mark_x (new_name); } diff --git a/src/unexcw.c b/src/unexcw.c index 0312a7328fb..12435a85051 100644 --- a/src/unexcw.c +++ b/src/unexcw.c @@ -316,13 +316,13 @@ unexec (const char *outfile, const char *infile) ret2 = write (fd_out, buffer, ret); assert (ret2 == ret); } - ret = close (fd_in); + ret = emacs_close (fd_in); assert (ret == 0); bss_sbrk_did_unexec = 1; fixup_executable (fd_out); bss_sbrk_did_unexec = 0; - ret = close (fd_out); + ret = emacs_close (fd_out); assert (ret == 0); } diff --git a/src/unexelf.c b/src/unexelf.c index 28847157e40..e2412393286 100644 --- a/src/unexelf.c +++ b/src/unexelf.c @@ -1312,13 +1312,13 @@ temacs: /* Close the files and make the new file executable. */ #if MAP_ANON == 0 - close (mmap_fd); + emacs_close (mmap_fd); #endif - if (close (old_file) != 0) + if (emacs_close (old_file) != 0) fatal ("Can't close (%s): %s", old_name, strerror (errno)); - if (close (new_file) != 0) + if (emacs_close (new_file) != 0) fatal ("Can't close (%s): %s", new_name, strerror (errno)); if (stat (new_name, &stat_buf) != 0) diff --git a/src/unexhp9k800.c b/src/unexhp9k800.c index 0f6eb87ee01..bee2517307a 100644 --- a/src/unexhp9k800.c +++ b/src/unexhp9k800.c @@ -306,6 +306,6 @@ unexec (const char *new_name, /* name of the new a.out file to be created * write_header (new, &hdr, &auxhdr); /* Close the binary file */ - close (old); - close (new); + emacs_close (old); + emacs_close (new); } diff --git a/src/unexmacosx.c b/src/unexmacosx.c index 2bc6de177eb..87848b012ba 100644 --- a/src/unexmacosx.c +++ b/src/unexmacosx.c @@ -1332,7 +1332,7 @@ unexec (const char *outfile, const char *infile) outfd = emacs_open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0755); if (outfd < 0) { - close (infd); + emacs_close (infd); unexec_error ("cannot open output file `%s'", outfile); } @@ -1346,7 +1346,7 @@ unexec (const char *outfile, const char *infile) dump_it (); - close (outfd); + emacs_close (outfd); } 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); extern void *e_malloc (size_t); extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, EMACS_TIME *, void *); +extern int sys_dup (int); + @@ -6719,10 +6721,16 @@ sys_sendto (int s, const char * buf, int len, int flags, } /* Windows does not have an fcntl function. Provide an implementation - solely for making sockets non-blocking. */ + good enough for Emacs. */ int fcntl (int s, int cmd, int options) { + /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always + invoked in a context where fd1 is closed and all descriptors less + than fd1 are open, so sys_dup is an adequate implementation. */ + if (cmd == F_DUPFD_CLOEXEC) + return sys_dup (s); + if (winsock_lib == NULL) { errno = ENETDOWN; @@ -6864,13 +6872,14 @@ sys_dup2 (int src, int dst) return rc; } -/* Unix pipe() has only one arg */ int -sys_pipe (int * phandles) +pipe2 (int * phandles, int pipe2_flags) { int rc; unsigned flags; + eassert (pipe2_flags == O_CLOEXEC); + /* make pipe handles non-inheritable; when we spawn a child, we replace the relevant handle with an inheritable one. Also put 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); extern int fchmod (int, mode_t); extern int sys_rename_replace (char const *, char const *, BOOL); -extern int sys_pipe (int *); +extern int pipe2 (int *, int); extern void set_process_dir (char *); extern int sys_spawnve (int, char *, char **, char **); diff --git a/src/xdisp.c b/src/xdisp.c index 5869ce5fdfa..12b294e6800 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -12589,6 +12589,7 @@ static void debug_method_add (struct window *, char const *, ...) static void debug_method_add (struct window *w, char const *fmt, ...) { + void *ptr = w; char *method = w->desired_matrix->method; int len = strlen (method); int size = sizeof w->desired_matrix->method; @@ -12607,7 +12608,7 @@ debug_method_add (struct window *w, char const *fmt, ...) if (trace_redisplay_p) fprintf (stderr, "%p (%s): %s\n", - w, + ptr, ((BUFFERP (w->contents) && STRINGP (BVAR (XBUFFER (w->contents), name))) ? SSDATA (BVAR (XBUFFER (w->contents), name)) 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) static void fatal (char *msg, char *prog) { - if (errno) - perror (prog); - - (void) fprintf (stderr, msg, prog); + fprintf (stderr, msg, prog); exit (1); } 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 { SEEN_HINTSTYLE = 0x10, SEEN_DPI = 0x20, SEEN_FONT = 0x40, - SEEN_TB_STYLE = 0x80, + SEEN_TB_STYLE = 0x80 }; struct xsettings { @@ -687,7 +687,7 @@ apply_xft_settings (struct x_display_info *dpyinfo, { static char const format[] = "Antialias: %d, Hinting: %d, RGBA: %d, LCDFilter: %d, " - "Hintstyle: %d, DPI: %lf"; + "Hintstyle: %d, DPI: %f"; enum { d_formats = 5, @@ -696,7 +696,7 @@ apply_xft_settings (struct x_display_info *dpyinfo, max_f_integer_digits = DBL_MAX_10_EXP + 1, f_precision = 6, lf_growth = (sizeof "-." + max_f_integer_digits + f_precision - - sizeof "%lf") + - sizeof "%f") }; char buf[sizeof format + d_formats * d_growth + lf_formats * lf_growth]; diff --git a/src/xterm.c b/src/xterm.c index f0b95d585e3..818b69cc41d 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2647,7 +2647,10 @@ x_draw_underwave (struct glyph_string *s) /* Find and set clipping rectangle */ - wave_clip = (XRectangle){ x0, y0, width, wave_height }; + wave_clip.x = x0; + wave_clip.y = y0; + wave_clip.width = width; + wave_clip.height = wave_height; get_glyph_string_clip_rect (s, &string_clip); if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip)) @@ -10191,71 +10194,73 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) } { - const struct + static const struct { const char *name; - Atom *atom; + int offset; } atom_refs[] = { - { "WM_PROTOCOLS", &dpyinfo->Xatom_wm_protocols }, - { "WM_TAKE_FOCUS", &dpyinfo->Xatom_wm_take_focus }, - { "WM_SAVE_YOURSELF", &dpyinfo->Xatom_wm_save_yourself }, - { "WM_DELETE_WINDOW", &dpyinfo->Xatom_wm_delete_window }, - { "WM_CHANGE_STATE", &dpyinfo->Xatom_wm_change_state }, - { "WM_CONFIGURE_DENIED", &dpyinfo->Xatom_wm_configure_denied }, - { "WM_MOVED", &dpyinfo->Xatom_wm_window_moved }, - { "WM_CLIENT_LEADER", &dpyinfo->Xatom_wm_client_leader }, - { "Editres", &dpyinfo->Xatom_editres }, - { "CLIPBOARD", &dpyinfo->Xatom_CLIPBOARD }, - { "TIMESTAMP", &dpyinfo->Xatom_TIMESTAMP }, - { "TEXT", &dpyinfo->Xatom_TEXT }, - { "COMPOUND_TEXT", &dpyinfo->Xatom_COMPOUND_TEXT }, - { "UTF8_STRING", &dpyinfo->Xatom_UTF8_STRING }, - { "DELETE", &dpyinfo->Xatom_DELETE }, - { "MULTIPLE", &dpyinfo->Xatom_MULTIPLE }, - { "INCR", &dpyinfo->Xatom_INCR }, - { "_EMACS_TMP_", &dpyinfo->Xatom_EMACS_TMP }, - { "TARGETS", &dpyinfo->Xatom_TARGETS }, - { "NULL", &dpyinfo->Xatom_NULL }, - { "ATOM", &dpyinfo->Xatom_ATOM }, - { "ATOM_PAIR", &dpyinfo->Xatom_ATOM_PAIR }, - { "CLIPBOARD_MANAGER", &dpyinfo->Xatom_CLIPBOARD_MANAGER }, - { "_XEMBED_INFO", &dpyinfo->Xatom_XEMBED_INFO }, +#define ATOM_REFS_INIT(string, member) \ + { string, offsetof (struct x_display_info, member) }, + ATOM_REFS_INIT ("WM_PROTOCOLS", Xatom_wm_protocols) + ATOM_REFS_INIT ("WM_TAKE_FOCUS", Xatom_wm_take_focus) + ATOM_REFS_INIT ("WM_SAVE_YOURSELF", Xatom_wm_save_yourself) + ATOM_REFS_INIT ("WM_DELETE_WINDOW", Xatom_wm_delete_window) + ATOM_REFS_INIT ("WM_CHANGE_STATE", Xatom_wm_change_state) + ATOM_REFS_INIT ("WM_CONFIGURE_DENIED", Xatom_wm_configure_denied) + ATOM_REFS_INIT ("WM_MOVED", Xatom_wm_window_moved) + ATOM_REFS_INIT ("WM_CLIENT_LEADER", Xatom_wm_client_leader) + ATOM_REFS_INIT ("Editres", Xatom_editres) + ATOM_REFS_INIT ("CLIPBOARD", Xatom_CLIPBOARD) + ATOM_REFS_INIT ("TIMESTAMP", Xatom_TIMESTAMP) + ATOM_REFS_INIT ("TEXT", Xatom_TEXT) + ATOM_REFS_INIT ("COMPOUND_TEXT", Xatom_COMPOUND_TEXT) + ATOM_REFS_INIT ("UTF8_STRING", Xatom_UTF8_STRING) + ATOM_REFS_INIT ("DELETE", Xatom_DELETE) + ATOM_REFS_INIT ("MULTIPLE", Xatom_MULTIPLE) + ATOM_REFS_INIT ("INCR", Xatom_INCR) + ATOM_REFS_INIT ("_EMACS_TMP_", Xatom_EMACS_TMP) + ATOM_REFS_INIT ("TARGETS", Xatom_TARGETS) + ATOM_REFS_INIT ("NULL", Xatom_NULL) + ATOM_REFS_INIT ("ATOM", Xatom_ATOM) + ATOM_REFS_INIT ("ATOM_PAIR", Xatom_ATOM_PAIR) + ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER) + ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO) /* For properties of font. */ - { "PIXEL_SIZE", &dpyinfo->Xatom_PIXEL_SIZE }, - { "AVERAGE_WIDTH", &dpyinfo->Xatom_AVERAGE_WIDTH }, - { "_MULE_BASELINE_OFFSET", &dpyinfo->Xatom_MULE_BASELINE_OFFSET }, - { "_MULE_RELATIVE_COMPOSE", &dpyinfo->Xatom_MULE_RELATIVE_COMPOSE }, - { "_MULE_DEFAULT_ASCENT", &dpyinfo->Xatom_MULE_DEFAULT_ASCENT }, + ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE) + ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH) + ATOM_REFS_INIT ("_MULE_BASELINE_OFFSET", Xatom_MULE_BASELINE_OFFSET) + ATOM_REFS_INIT ("_MULE_RELATIVE_COMPOSE", Xatom_MULE_RELATIVE_COMPOSE) + ATOM_REFS_INIT ("_MULE_DEFAULT_ASCENT", Xatom_MULE_DEFAULT_ASCENT) /* Ghostscript support. */ - { "DONE", &dpyinfo->Xatom_DONE }, - { "PAGE", &dpyinfo->Xatom_PAGE }, - { "SCROLLBAR", &dpyinfo->Xatom_Scrollbar }, - { "_XEMBED", &dpyinfo->Xatom_XEMBED }, + ATOM_REFS_INIT ("DONE", Xatom_DONE) + ATOM_REFS_INIT ("PAGE", Xatom_PAGE) + ATOM_REFS_INIT ("SCROLLBAR", Xatom_Scrollbar) + ATOM_REFS_INIT ("_XEMBED", Xatom_XEMBED) /* EWMH */ - { "_NET_WM_STATE", &dpyinfo->Xatom_net_wm_state }, - { "_NET_WM_STATE_FULLSCREEN", &dpyinfo->Xatom_net_wm_state_fullscreen }, - { "_NET_WM_STATE_MAXIMIZED_HORZ", - &dpyinfo->Xatom_net_wm_state_maximized_horz }, - { "_NET_WM_STATE_MAXIMIZED_VERT", - &dpyinfo->Xatom_net_wm_state_maximized_vert }, - { "_NET_WM_STATE_STICKY", &dpyinfo->Xatom_net_wm_state_sticky }, - { "_NET_WM_STATE_HIDDEN", &dpyinfo->Xatom_net_wm_state_hidden }, - { "_NET_WM_WINDOW_TYPE", &dpyinfo->Xatom_net_window_type }, - { "_NET_WM_WINDOW_TYPE_TOOLTIP", - &dpyinfo->Xatom_net_window_type_tooltip }, - { "_NET_WM_ICON_NAME", &dpyinfo->Xatom_net_wm_icon_name }, - { "_NET_WM_NAME", &dpyinfo->Xatom_net_wm_name }, - { "_NET_SUPPORTED", &dpyinfo->Xatom_net_supported }, - { "_NET_SUPPORTING_WM_CHECK", &dpyinfo->Xatom_net_supporting_wm_check }, - { "_NET_WM_WINDOW_OPACITY", &dpyinfo->Xatom_net_wm_window_opacity }, - { "_NET_ACTIVE_WINDOW", &dpyinfo->Xatom_net_active_window }, - { "_NET_FRAME_EXTENTS", &dpyinfo->Xatom_net_frame_extents }, - { "_NET_CURRENT_DESKTOP", &dpyinfo->Xatom_net_current_desktop }, - { "_NET_WORKAREA", &dpyinfo->Xatom_net_workarea }, + ATOM_REFS_INIT ("_NET_WM_STATE", Xatom_net_wm_state) + ATOM_REFS_INIT ("_NET_WM_STATE_FULLSCREEN", Xatom_net_wm_state_fullscreen) + ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_HORZ", + Xatom_net_wm_state_maximized_horz) + ATOM_REFS_INIT ("_NET_WM_STATE_MAXIMIZED_VERT", + Xatom_net_wm_state_maximized_vert) + ATOM_REFS_INIT ("_NET_WM_STATE_STICKY", Xatom_net_wm_state_sticky) + ATOM_REFS_INIT ("_NET_WM_STATE_HIDDEN", Xatom_net_wm_state_hidden) + ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE", Xatom_net_window_type) + ATOM_REFS_INIT ("_NET_WM_WINDOW_TYPE_TOOLTIP", + Xatom_net_window_type_tooltip) + ATOM_REFS_INIT ("_NET_WM_ICON_NAME", Xatom_net_wm_icon_name) + ATOM_REFS_INIT ("_NET_WM_NAME", Xatom_net_wm_name) + ATOM_REFS_INIT ("_NET_SUPPORTED", Xatom_net_supported) + ATOM_REFS_INIT ("_NET_SUPPORTING_WM_CHECK", Xatom_net_supporting_wm_check) + ATOM_REFS_INIT ("_NET_WM_WINDOW_OPACITY", Xatom_net_wm_window_opacity) + ATOM_REFS_INIT ("_NET_ACTIVE_WINDOW", Xatom_net_active_window) + ATOM_REFS_INIT ("_NET_FRAME_EXTENTS", Xatom_net_frame_extents) + ATOM_REFS_INIT ("_NET_CURRENT_DESKTOP", Xatom_net_current_desktop) + ATOM_REFS_INIT ("_NET_WORKAREA", Xatom_net_workarea) /* Session management */ - { "SM_CLIENT_ID", &dpyinfo->Xatom_SM_CLIENT_ID }, - { "_XSETTINGS_SETTINGS", &dpyinfo->Xatom_xsettings_prop }, - { "MANAGER", &dpyinfo->Xatom_xsettings_mgr }, + ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID) + ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop) + ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr) }; int i; @@ -10280,7 +10285,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) False, atoms_return); for (i = 0; i < atom_count; i++) - *atom_refs[i].atom = atoms_return[i]; + *(Atom *) ((char *) dpyinfo + atom_refs[i].offset) = atoms_return[i]; /* Manual copy of last atom */ dpyinfo->Xatom_xsettings_sel = atoms_return[i]; |
