aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2013-05-15 19:15:07 +0300
committerEli Zaretskii2013-05-15 19:15:07 +0300
commitd14365f9411ab4b20db6c455aa9cf24ce6a0bcb1 (patch)
treef547c3f203c903b118348061eb0fd2359c94d324 /src
parentf94b5742a3e9bc7114c6e2cd85a2371381cba4d3 (diff)
parente3772e9833f971a450562350dc233bf00be7c5eb (diff)
downloademacs-d14365f9411ab4b20db6c455aa9cf24ce6a0bcb1.tar.gz
emacs-d14365f9411ab4b20db6c455aa9cf24ce6a0bcb1.zip
Merge from trunk, configury not fixed yet.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog230
-rw-r--r--src/Makefile.in17
-rw-r--r--src/buffer.c4
-rw-r--r--src/callint.c12
-rw-r--r--src/dispextern.h15
-rw-r--r--src/doc.c22
-rw-r--r--src/fileio.c107
-rw-r--r--src/filelock.c10
-rw-r--r--src/gtkutil.c9
-rw-r--r--src/image.c19
-rw-r--r--src/lread.c28
-rw-r--r--src/makefile.w32-in4
-rw-r--r--src/minibuf.c34
-rw-r--r--src/nsfns.m251
-rw-r--r--src/nsfont.m7
-rw-r--r--src/nsmenu.m8
-rw-r--r--src/regex.c387
-rw-r--r--src/unexelf.c204
-rw-r--r--src/w32fns.c25
-rw-r--r--src/xdisp.c71
-rw-r--r--src/xfns.c583
-rw-r--r--src/xterm.c4
-rw-r--r--src/xterm.h21
23 files changed, 1557 insertions, 515 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 4245a1f0256..0b4ccb0708a 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,232 @@
12013-05-15 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * regex.c (regex_compile) [\=, \>, \<]: Don't forget to set laststart.
4
52013-05-14 Eli Zaretskii <eliz@gnu.org>
6
7 * w32fns.c (w32_wnd_proc): Don't call WINDOW_HEADER_LINE_HEIGHT
8 unless we know that the window w is a leaf window.
9 Another attempt at solving bug#14062.
10
112013-05-14 Jan Djärv <jan.h.d@swipnet.se>
12
13 * nsfont.m (ns_spec_to_descriptor): Retain and autorelease
14 fdesc (Bug#14375).
15
162013-05-12 Paul Eggert <eggert@cs.ucla.edu>
17
18 * image.c (gif_load): Check that subimages fit (Bug#14345).
19
202013-05-09 Stefan Monnier <monnier@iro.umontreal.ca>
21
22 * lread.c (skip_dyn_eof): New function.
23 (read1): Use it to skip the end of a file in response to #@00.
24
25 * doc.c (get_doc_string): Slightly relax the sanity checking.
26
272013-05-09 Jan Djärv <jan.h.d@swipnet.se>
28
29 * nsfns.m: Include IOGraphicsLib.h if Cocoa.
30 (Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource): Declare.
31 (MonitorInfo): New struct.
32 (free_monitors, ns_screen_name, ns_make_monitor_attribute_list)
33 (Fns_display_monitor_attributes_list): New functions.
34 (display-usable-bounds): Remove.
35 (syms_of_nsfns): DEFSYM Qgeometry, Qworkarea, Qmm_size, Qframes and
36 Qsource.
37
382013-05-09 Paul Eggert <eggert@cs.ucla.edu>
39
40 * xterm.h (GTK_PREREQ): Remove, replacing with GTK_CHECK_VERSION.
41 (GTK_CHECK_VERSION): New macro, if not already defined.
42 All uses of GTK_PREREQ, GTK_MAJOR_VERSION, etc.
43 replaced by GTK_CHECK_VERSION.
44
452013-05-08 Paul Eggert <eggert@cs.ucla.edu>
46
47 * xterm.h (GTK_PREREQ): New macro.
48 All simple uses of GTK_MAJOR_VERSION and GTK_MINOR_VERSION changed
49 to use this macro instead, for consistency and clarity.
50
512013-05-08 Eli Zaretskii <eliz@gnu.org>
52
53 * xdisp.c (row_for_charpos_p): New function, with code of
54 cursor_row_p, but accepts an additional argument CHARPOS instead
55 of using a hardcoded PT.
56 (cursor_row_p): Call row_for_charpos_p with 2nd argument PT.
57 (row_containing_pos): Call row_for_charpos_p instead of partially
58 doing the same. Fixes cursor positioning under longlines-mode
59 when longlines-show-effect includes more than one newline, when
60 moving the cursor vertically up.
61
622013-05-08 Juanma Barranquero <lekktu@gmail.com>
63
64 * makefile.w32-in (ACL_H): New macro.
65 ($(BLD)/fileio.$(O)): Update dependencies.
66
672013-05-07 Paul Eggert <eggert@cs.ucla.edu>
68
69 Use Gnulib ACL implementation, for benefit of Solaris etc. (Bug#14295)
70 * Makefile.in (LIB_ACL): New macro.
71 (LIBACL_LIBS): Remove.
72 (LIBES): Use LIB_ACL, not LIBACL_LIBS.
73 * fileio.c: Include <acl.h>.
74 Use HAVE_ACL_SET_FILE rather than HAVE_POSIX_ACL.
75 (ACL_NOT_WELL_SUPPORTED): Remove. All uses replaced by
76 !acl_errno_valid.
77 (Fcopy_file) [!WINDOWSNT]: Use qcopy_acl instead of rolling
78 it ourselves.
79
80 * unexelf.c: Don't assume ElfW (Half) fits in int.
81 (entry_address, find_section, unexec): Use ptrdiff_t, not int,
82 when dealing with ElfW (Half) values, since they can exceed 2**31
83 on 64-bit OpenBSD hosts. Problem reported privately by Han Boetes.
84 (entry_address): Omit unused NUM arg. All uses changed.
85
862013-05-07 Juri Linkov <juri@jurta.org>
87
88 * callint.c (Fcall_interactively): Set `visargs[i]' for code 'n'
89 to the string converted from number with `Fnumber_to_string'.
90 (Bug#14254)
91
922013-05-07 Paul Eggert <eggert@cs.ucla.edu>
93
94 * xfns.c (x_get_net_workarea): Define only if !GTK || GTK<3.4.
95 This fixes a problem introduced by my previous change.
96
972013-05-07 Glenn Morris <rgm@gnu.org>
98
99 * lread.c (readchar): Don't read from a dead buffer. (Bug#14280)
100
1012013-05-07 Jan Djärv <jan.h.d@swipnet.se>
102
103 * xfns.c: Move misplaced ifndef USE_GTK from previous checkin.
104
1052013-05-07 Paul Eggert <eggert@cs.ucla.edu>
106
107 Static checking by GCC 4.8.0.
108 * xfns.c (x_get_net_workarea, struct MonitorInfo, free_monitors)
109 (x_get_monitor_for_frame, x_make_monitor_attribute_list)
110 (x_get_monitor_attributes_fallback)
111 (x_get_monitor_attributes_xinerama)
112 (x_get_monitor_attributes_xrandr, x_get_monitor_attributes):
113 Define only if USE_GTK.
114 (free_monitors): Define only if HAVE_XINERAMA || HAVE_XRANDR.
115 (x_get_monitor_attributes_fallback): Omit unused locals.
116 (x_get_monitor_attributes_xinerama, Fx_display_monitor_attributes_list):
117 Use double, not float, to avoid mixed-mode floating point arithmetic.
118
1192013-05-07 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
120 Jan Djärv <jan.h.d@swipnet.se>
121
122 * Makefile.in (XRANDR_LIBS, XRANDR_CFLAGS, XINERAMA_LIBS)
123 (XINERAMA_CFLAGS): New macros.
124 (ALL_CFLAGS, LIBES): Use them.
125
126 * xfns.c: Include <X11/extensions/Xrandr.h> if HAVE_XRANDR, and
127 include <X11/extensions/Xinerama.h> if HAVE_XINERAMA.
128 (Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource): New variables.
129 (syms_of_xfns): DEFSYM them.
130 (struct MonitorInfo): New struct.
131 (x_get_net_workarea, free_monitors, x_get_monitor_for_frame)
132 (x_make_monitor_attribute_list, x_get_monitor_attributes_fallback)
133 (x_get_monitor_attributes_xrandr, x_get_monitor_attributes)
134 (x_get_monitor_attributes_xinerama): New functions.
135 (Fx_display_monitor_attributes_list): New primitive.
136 (syms_of_xfns): Defsubr it.
137
138 * xterm.h (x_display_info): Add Xatom_net_workarea and
139 Xatom_net_current_desktop.
140
141 * xterm.c (x_term_init): Initialize dpyinfo->Xatom_net_workarea
142 and dpyinfo->Xatom_net_current_desktop.
143
1442013-05-06 Eli Zaretskii <eliz@gnu.org>
145
146 * xdisp.c (pos_visible_p): Use the special code for finding the
147 beginning of a display property or overlay for any "replacing"
148 display property, not just for display strings. This solves
149 incorrect reporting of position by posn-at-point. (Bug#14241)
150
1512013-05-06 Paul Eggert <eggert@cs.ucla.edu>
152
153 * unexelf.c: Fix some 32-bit integer problems, notably when debugging.
154 Include <limits.h>, <stdbool.h>, <intprops.h>, <verify.h>.
155 Verify that ElfW (Half) fits in int.
156 (fatal): Use same signature as lisp.h.
157 (UNEXELF_DEBUG): New macro, replacing DEBUG, so that people can
158 configure and build with -DUNEXELF_DEBUG without worrying about
159 other modules that use DEBUG.
160 (DEBUG_LOG) [UNEXELF_DEBUG]: New macro. All debug code that prints
161 possibly-wide integers now uses it instead of plain fprintf.
162 (entry_address): New function, which avoids problems with 32-bit
163 overflow on 64-bit hosts.
164 (OLD_SECTION_H, NEW_SECTION_H, NEW_PROGRAM_H): Use it.
165 (round_up): Don't assume the remainder fits in int.
166 (find_section): Use bool for boolean. Simplify debug code.
167 (unexec): Don't assume file sizes fit in int or size_t.
168 Omit unnecessary trailing newline in 'fatal' format.
169 Use strerror rather than outputting decimal error number.
170 Remove unused code when emacs is not defined;
171 this file relies on Emacs now.
172 Don't assume e_phnum and e_shnum are positive.
173
174 * regex.c: Fix problems when DEBUG is defined.
175 (extract_number, extract_number_and_incr): Define regardless of
176 whether DEBUG is defined; that's simpler and makes the code less
177 likely to go stale in the normal case when DEBUG is not defined.
178 Return int rather than taking an int * arg. All callers changed.
179 (DEBUG_PRINT1, DEBUG_PRINT2, DEBUG_PRINT3, DEBUG_PRINT4):
180 Remove, replacing with ...
181 (DEBUG_PRINT): New macro. All callers changed.
182 (DEBUG_COMPILES_ARGUMENTS): New macro.
183 (print_fastmap, print_partial_compiled_pattern) [DEBUG]:
184 (print_compiled_pattern, print_double_string) [DEBUG]:
185 Use prototype rather than old-style definition.
186 (print_partial_compiled_pattern, print_compiled_pattern) [DEBUG]:
187 (ENSURE_FAIL_STACK, PUSH_FAILURE_REG) [DEBUG]:
188 (POP_FAILURE_REG_OR_COUNT, PUSH_FAILURE_POINT) [DEBUG]:
189 (POP_FAILURE_POINT, re_match_2_internal) [DEBUG]:
190 Don't assume ptrdiff_t, size_t, and long are the same width as int.
191 (POINTER_TO_OFFSET): Return ptrdiff_t, not regoff_t.
192 This matters only when DEBUG is defined.
193
1942013-05-05 Eli Zaretskii <eliz@gnu.org>
195
196 * xdisp.c (set_iterator_to_next): Set the
197 ignore_overlay_strings_at_pos_p flag only if we are _really_
198 iterating over an overlay string, as indicated by the
199 current.overlay_string_index member. (Bug#14306)
200
2012013-05-05 Jan Djärv <jan.h.d@swipnet.se>
202
203 * nsmenu.m (ns_update_menubar): Move initialization of submenuTitle
204 to where it is used, to avoid autorelease issues (Bug#14050).
205
2062013-05-05 Paul Eggert <eggert@cs.ucla.edu>
207
208 `write-region-inhibit-fsync' defaults to noninteractive (Bug#14273).
209 * fileio.c (syms_of_fileio): Implement this.
210 * filelock.c (create_lock_file): If symbolic links don't work, so
211 we use a regular file as a lock file, do not fsync the lock file;
212 it's not needed.
213
2142013-05-04 Stefan Monnier <monnier@iro.umontreal.ca>
215
216 * minibuf.c (Fread_minibuffer, Feval_minibuffer): Move to Elisp.
217 (syms_of_minibuf): Adjust accodingly.
218 * lread.c (Fread):
219 * callint.c (Fcall_interactively): Adjust calls accordingly.
220
2212013-05-04 Eli Zaretskii <eliz@gnu.org>
222
223 * dispextern.h (WINDOW_WANTS_HEADER_LINE_P): Verify that
224 w->contents is a buffer before computing everything else.
225 Use parentheses to disambiguate last part of the condition.
226
227 * w32fns.c (w32_wnd_proc): Remove temporary code used to trap
228 assertion violations. (Bug#14062)
229
12013-05-01 David Reitter <david.reitter@gmail.com> 2302013-05-01 David Reitter <david.reitter@gmail.com>
2 231
3 * nsfns.m (ns_tooltip): Initialize. 232 * nsfns.m (ns_tooltip): Initialize.
@@ -35,6 +264,7 @@
35 size. 264 size.
36 265
372013-04-26 Paul Eggert <eggert@cs.ucla.edu> 2662013-04-26 Paul Eggert <eggert@cs.ucla.edu>
267
38 Port better to AIX (Bug#14258). 268 Port better to AIX (Bug#14258).
39 * lisp.h (ENUM_BF) [__IBMC__]: Make it 'unsigned int' here, too, 269 * lisp.h (ENUM_BF) [__IBMC__]: Make it 'unsigned int' here, too,
40 to pacify AIX xlc. 270 to pacify AIX xlc.
diff --git a/src/Makefile.in b/src/Makefile.in
index d12f8dbe130..2e1764723ec 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -137,6 +137,7 @@ LIBOTF_LIBS = @LIBOTF_LIBS@
137M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@ 137M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@
138M17N_FLT_LIBS = @M17N_FLT_LIBS@ 138M17N_FLT_LIBS = @M17N_FLT_LIBS@
139 139
140LIB_ACL=@LIB_ACL@
140LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@ 141LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@
141LIB_EACCESS=@LIB_EACCESS@ 142LIB_EACCESS=@LIB_EACCESS@
142LIB_FDATASYNC=@LIB_FDATASYNC@ 143LIB_FDATASYNC=@LIB_FDATASYNC@
@@ -232,6 +233,12 @@ IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@
232LIBXML2_LIBS = @LIBXML2_LIBS@ 233LIBXML2_LIBS = @LIBXML2_LIBS@
233LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ 234LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
234 235
236XRANDR_LIBS = @XRANDR_LIBS@
237XRANDR_CFLAGS = @XRANDR_CFLAGS@
238
239XINERAMA_LIBS = @XINERAMA_LIBS@
240XINERAMA_CFLAGS = @XINERAMA_CFLAGS@
241
235## widget.o if USE_X_TOOLKIT, otherwise empty. 242## widget.o if USE_X_TOOLKIT, otherwise empty.
236WIDGET_OBJ=@WIDGET_OBJ@ 243WIDGET_OBJ=@WIDGET_OBJ@
237 244
@@ -288,8 +295,6 @@ LIBSELINUX_LIBS = @LIBSELINUX_LIBS@
288LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@ 295LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
289LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@ 296LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
290 297
291LIBACL_LIBS = @LIBACL_LIBS@
292
293LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@ 298LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@
294 299
295INTERVALS_H = dispextern.h intervals.h composite.h 300INTERVALS_H = dispextern.h intervals.h composite.h
@@ -329,7 +334,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
329 -I$(lib) -I$(srcdir)/../lib \ 334 -I$(lib) -I$(srcdir)/../lib \
330 $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \ 335 $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \
331 $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ 336 $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \
332 $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ 337 $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) \
333 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ 338 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
334 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ 339 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
335 $(LIBGNUTLS_CFLAGS) \ 340 $(LIBGNUTLS_CFLAGS) \
@@ -407,13 +412,13 @@ ALLOBJS = $(FIRSTFILE_OBJ) $(VMLIMIT_OBJ) $(obj) $(otherobj)
407## Construct full set of libraries to be linked. 412## Construct full set of libraries to be linked.
408LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ 413LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
409 $(LIBX_OTHER) $(LIBSOUND) \ 414 $(LIBX_OTHER) $(LIBSOUND) \
410 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) \ 415 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \
411 $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ 416 $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
412 $(LIB_EXECINFO) \ 417 $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) \
413 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \ 418 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \
414 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ 419 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
415 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ 420 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
416 $(LIBACL_LIBS) $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \ 421 $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \
417 $(LIB_MATH) 422 $(LIB_MATH)
418 423
419all: emacs$(EXEEXT) $(OTHER_FILES) 424all: emacs$(EXEEXT) $(OTHER_FILES)
diff --git a/src/buffer.c b/src/buffer.c
index 3810d3db079..abebdf21135 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5501,6 +5501,8 @@ This is the same as (default-value 'left-margin). */);
5501 DEFVAR_BUFFER_DEFAULTS ("default-tab-width", 5501 DEFVAR_BUFFER_DEFAULTS ("default-tab-width",
5502 tab_width, 5502 tab_width,
5503 doc: /* Default value of `tab-width' for buffers that do not override it. 5503 doc: /* Default value of `tab-width' for buffers that do not override it.
5504NOTE: This controls the display width of a TAB character, and not
5505the size of an indentation step.
5504This is the same as (default-value 'tab-width). */); 5506This is the same as (default-value 'tab-width). */);
5505 5507
5506 DEFVAR_BUFFER_DEFAULTS ("default-case-fold-search", 5508 DEFVAR_BUFFER_DEFAULTS ("default-case-fold-search",
@@ -5692,6 +5694,8 @@ Linefeed indents to this column in Fundamental mode. */);
5692 DEFVAR_PER_BUFFER ("tab-width", &BVAR (current_buffer, tab_width), 5694 DEFVAR_PER_BUFFER ("tab-width", &BVAR (current_buffer, tab_width),
5693 Qintegerp, 5695 Qintegerp,
5694 doc: /* Distance between tab stops (for display of tab characters), in columns. 5696 doc: /* Distance between tab stops (for display of tab characters), in columns.
5697NOTE: This controls the display width of a TAB character, and not
5698the size of an indentation step.
5695This should be an integer greater than zero. */); 5699This should be an integer greater than zero. */);
5696 5700
5697 DEFVAR_PER_BUFFER ("ctl-arrow", &BVAR (current_buffer, ctl_arrow), Qnil, 5701 DEFVAR_PER_BUFFER ("ctl-arrow", &BVAR (current_buffer, ctl_arrow), Qnil,
diff --git a/src/callint.c b/src/callint.c
index 940ff3ed249..0651b68dc05 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -251,6 +251,9 @@ invoke it. If KEYS is omitted or nil, the return value of
251`this-command-keys-vector' is used. */) 251`this-command-keys-vector' is used. */)
252 (Lisp_Object function, Lisp_Object record_flag, Lisp_Object keys) 252 (Lisp_Object function, Lisp_Object record_flag, Lisp_Object keys)
253{ 253{
254 /* `args' will contain the array of arguments to pass to the function.
255 `visargs' will contain the same list but in a nicer form, so that if we
256 pass it to `Fformat' it will be understandable to a human. */
254 Lisp_Object *args, *visargs; 257 Lisp_Object *args, *visargs;
255 Lisp_Object specs; 258 Lisp_Object specs;
256 Lisp_Object filter_specs; 259 Lisp_Object filter_specs;
@@ -685,6 +688,9 @@ invoke it. If KEYS is omitted or nil, the return value of
685 goto have_prefix_arg; 688 goto have_prefix_arg;
686 case 'n': /* Read number from minibuffer. */ 689 case 'n': /* Read number from minibuffer. */
687 args[i] = call1 (Qread_number, callint_message); 690 args[i] = call1 (Qread_number, callint_message);
691 /* Passing args[i] directly stimulates compiler bug. */
692 teml = args[i];
693 visargs[i] = Fnumber_to_string (teml);
688 break; 694 break;
689 695
690 case 'P': /* Prefix arg in raw form. Does no I/O. */ 696 case 'P': /* Prefix arg in raw form. Does no I/O. */
@@ -733,12 +739,12 @@ invoke it. If KEYS is omitted or nil, the return value of
733 break; 739 break;
734 740
735 case 'x': /* Lisp expression read but not evaluated. */ 741 case 'x': /* Lisp expression read but not evaluated. */
736 args[i] = Fread_minibuffer (callint_message, Qnil); 742 args[i] = call1 (intern ("read-minibuffer"), callint_message);
737 visargs[i] = last_minibuf_string; 743 visargs[i] = last_minibuf_string;
738 break; 744 break;
739 745
740 case 'X': /* Lisp expression read and evaluated. */ 746 case 'X': /* Lisp expression read and evaluated. */
741 args[i] = Feval_minibuffer (callint_message, Qnil); 747 args[i] = call1 (intern ("eval-minibuffer"), callint_message);
742 visargs[i] = last_minibuf_string; 748 visargs[i] = last_minibuf_string;
743 break; 749 break;
744 750
@@ -790,6 +796,8 @@ invoke it. If KEYS is omitted or nil, the return value of
790 796
791 if (arg_from_tty || !NILP (record_flag)) 797 if (arg_from_tty || !NILP (record_flag))
792 { 798 {
799 /* We don't need `visargs' any more, so let's recycle it since we need
800 an array of just the same size. */
793 visargs[0] = function; 801 visargs[0] = function;
794 for (i = 1; i < nargs; i++) 802 for (i = 1; i < nargs; i++)
795 { 803 {
diff --git a/src/dispextern.h b/src/dispextern.h
index 5ce7b19f173..50a32ffaf8f 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1423,13 +1423,14 @@ struct glyph_string
1423/* Value is true if window W wants a header line. */ 1423/* Value is true if window W wants a header line. */
1424 1424
1425#define WINDOW_WANTS_HEADER_LINE_P(W) \ 1425#define WINDOW_WANTS_HEADER_LINE_P(W) \
1426 (!MINI_WINDOW_P ((W)) \ 1426 (BUFFERP ((W)->contents) \
1427 && !(W)->pseudo_window_p \ 1427 ? (!MINI_WINDOW_P ((W)) \
1428 && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W)))) \ 1428 && !(W)->pseudo_window_p \
1429 && BUFFERP ((W)->contents) \ 1429 && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W)))) \
1430 && !NILP (BVAR (XBUFFER ((W)->contents), header_line_format)) \ 1430 && !NILP (BVAR (XBUFFER ((W)->contents), header_line_format)) \
1431 && WINDOW_TOTAL_LINES (W) > 1 \ 1431 && WINDOW_TOTAL_LINES (W) > \
1432 + !NILP (BVAR (XBUFFER ((W)->contents), mode_line_format))) 1432 (1 + !NILP (BVAR (XBUFFER ((W)->contents), mode_line_format)))) \
1433 : 0)
1433 1434
1434/* Return proper value to be used as baseline offset of font that has 1435/* Return proper value to be used as baseline offset of font that has
1435 ASCENT and DESCENT to draw characters by the font at the vertical 1436 ASCENT and DESCENT to draw characters by the font at the vertical
diff --git a/src/doc.c b/src/doc.c
index 7234fb38bf9..770cb1eb646 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -215,14 +215,20 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
215 if (CONSP (filepos)) 215 if (CONSP (filepos))
216 { 216 {
217 int test = 1; 217 int test = 1;
218 if (get_doc_string_buffer[offset - test++] != ' ') 218 /* A dynamic docstring should be either at the very beginning of a "#@
219 return Qnil; 219 comment" or right after a dynamic docstring delimiter (in case we
220 while (get_doc_string_buffer[offset - test] >= '0' 220 pack several such docstrings within the same comment). */
221 && get_doc_string_buffer[offset - test] <= '9') 221 if (get_doc_string_buffer[offset - test] != '\037')
222 test++; 222 {
223 if (get_doc_string_buffer[offset - test++] != '@' 223 if (get_doc_string_buffer[offset - test++] != ' ')
224 || get_doc_string_buffer[offset - test] != '#') 224 return Qnil;
225 return Qnil; 225 while (get_doc_string_buffer[offset - test] >= '0'
226 && get_doc_string_buffer[offset - test] <= '9')
227 test++;
228 if (get_doc_string_buffer[offset - test++] != '@'
229 || get_doc_string_buffer[offset - test] != '#')
230 return Qnil;
231 }
226 } 232 }
227 else 233 else
228 { 234 {
diff --git a/src/fileio.c b/src/fileio.c
index 1049522e5a9..fe1bce16ca0 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -36,7 +36,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
36#include <selinux/context.h> 36#include <selinux/context.h>
37#endif 37#endif
38 38
39#ifdef HAVE_POSIX_ACL 39#ifdef HAVE_ACL_SET_FILE
40#include <sys/acl.h> 40#include <sys/acl.h>
41#endif 41#endif
42 42
@@ -81,26 +81,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
81#define DRIVE_LETTER(x) c_tolower (x) 81#define DRIVE_LETTER(x) c_tolower (x)
82#endif 82#endif
83 83
84#ifdef HAVE_POSIX_ACL
85/* FIXME: this macro was copied from gnulib's private acl-internal.h
86 header file. */
87/* Recognize some common errors such as from an NFS mount that does
88 not support ACLs, even when local drives do. */
89#if defined __APPLE__ && defined __MACH__ /* Mac OS X */
90#define ACL_NOT_WELL_SUPPORTED(Err) \
91 ((Err) == ENOTSUP || (Err) == ENOSYS || (Err) == EINVAL || (Err) == EBUSY || (Err) == ENOENT)
92#elif defined EOPNOTSUPP /* Tru64 NFS */
93#define ACL_NOT_WELL_SUPPORTED(Err) \
94 ((Err) == ENOTSUP || (Err) == ENOSYS || (Err) == EINVAL || (Err) == EBUSY || (Err) == EOPNOTSUPP)
95#elif defined WINDOWSNT
96#define ACL_NOT_WELL_SUPPORTED(Err) ((Err) == ENOTSUP)
97#else
98#define ACL_NOT_WELL_SUPPORTED(Err) \
99 ((Err) == ENOTSUP || (Err) == ENOSYS || (Err) == EINVAL || (Err) == EBUSY)
100#endif
101#endif /* HAVE_POSIX_ACL */
102
103#include "systime.h" 84#include "systime.h"
85#include <acl.h>
104#include <allocator.h> 86#include <allocator.h>
105#include <careadlinkat.h> 87#include <careadlinkat.h>
106#include <stat-time.h> 88#include <stat-time.h>
@@ -1988,7 +1970,7 @@ entries (depending on how Emacs was built). */)
1988 security_context_t con; 1970 security_context_t con;
1989 int conlength = 0; 1971 int conlength = 0;
1990#endif 1972#endif
1991#ifdef HAVE_POSIX_ACL 1973#ifdef WINDOWSNT
1992 acl_t acl = NULL; 1974 acl_t acl = NULL;
1993#endif 1975#endif
1994 1976
@@ -2028,11 +2010,9 @@ entries (depending on how Emacs was built). */)
2028#ifdef WINDOWSNT 2010#ifdef WINDOWSNT
2029 if (!NILP (preserve_extended_attributes)) 2011 if (!NILP (preserve_extended_attributes))
2030 { 2012 {
2031#ifdef HAVE_POSIX_ACL
2032 acl = acl_get_file (SDATA (encoded_file), ACL_TYPE_ACCESS); 2013 acl = acl_get_file (SDATA (encoded_file), ACL_TYPE_ACCESS);
2033 if (acl == NULL && !ACL_NOT_WELL_SUPPORTED (errno)) 2014 if (acl == NULL && acl_errno_valid (errno))
2034 report_file_error ("Getting ACL", Fcons (file, Qnil)); 2015 report_file_error ("Getting ACL", Fcons (file, Qnil));
2035#endif
2036 } 2016 }
2037 if (!CopyFile (SDATA (encoded_file), 2017 if (!CopyFile (SDATA (encoded_file),
2038 SDATA (encoded_newname), 2018 SDATA (encoded_newname),
@@ -2069,17 +2049,15 @@ entries (depending on how Emacs was built). */)
2069 /* Restore original attributes. */ 2049 /* Restore original attributes. */
2070 SetFileAttributes (filename, attributes); 2050 SetFileAttributes (filename, attributes);
2071 } 2051 }
2072#ifdef HAVE_POSIX_ACL
2073 if (acl != NULL) 2052 if (acl != NULL)
2074 { 2053 {
2075 bool fail = 2054 bool fail =
2076 acl_set_file (SDATA (encoded_newname), ACL_TYPE_ACCESS, acl) != 0; 2055 acl_set_file (SDATA (encoded_newname), ACL_TYPE_ACCESS, acl) != 0;
2077 if (fail && !ACL_NOT_WELL_SUPPORTED (errno)) 2056 if (fail && acl_errno_valid (errno))
2078 report_file_error ("Setting ACL", Fcons (newname, Qnil)); 2057 report_file_error ("Setting ACL", Fcons (newname, Qnil));
2079 2058
2080 acl_free (acl); 2059 acl_free (acl);
2081 } 2060 }
2082#endif
2083#else /* not WINDOWSNT */ 2061#else /* not WINDOWSNT */
2084 immediate_quit = 1; 2062 immediate_quit = 1;
2085 ifd = emacs_open (SSDATA (encoded_file), O_RDONLY, 0); 2063 ifd = emacs_open (SSDATA (encoded_file), O_RDONLY, 0);
@@ -2103,12 +2081,6 @@ entries (depending on how Emacs was built). */)
2103 report_file_error ("Doing fgetfilecon", Fcons (file, Qnil)); 2081 report_file_error ("Doing fgetfilecon", Fcons (file, Qnil));
2104 } 2082 }
2105#endif 2083#endif
2106
2107#ifdef HAVE_POSIX_ACL
2108 acl = acl_get_fd (ifd);
2109 if (acl == NULL && !ACL_NOT_WELL_SUPPORTED (errno))
2110 report_file_error ("Getting ACL", Fcons (file, Qnil));
2111#endif
2112 } 2084 }
2113 2085
2114 if (out_st.st_mode != 0 2086 if (out_st.st_mode != 0
@@ -2156,7 +2128,7 @@ entries (depending on how Emacs was built). */)
2156 immediate_quit = 0; 2128 immediate_quit = 0;
2157 2129
2158#ifndef MSDOS 2130#ifndef MSDOS
2159 /* Preserve the original file modes, and if requested, also its 2131 /* Preserve the original file permissions, and if requested, also its
2160 owner and group. */ 2132 owner and group. */
2161 { 2133 {
2162 mode_t mode_mask = 07777; 2134 mode_t mode_mask = 07777;
@@ -2173,8 +2145,16 @@ entries (depending on how Emacs was built). */)
2173 mode_mask |= 02000; 2145 mode_mask |= 02000;
2174 } 2146 }
2175 } 2147 }
2176 if (fchmod (ofd, st.st_mode & mode_mask) != 0) 2148
2177 report_file_error ("Doing chmod", Fcons (newname, Qnil)); 2149 switch (!NILP (preserve_extended_attributes)
2150 ? qcopy_acl (SSDATA (encoded_file), ifd,
2151 SSDATA (encoded_newname), ofd,
2152 st.st_mode & mode_mask)
2153 : fchmod (ofd, st.st_mode & mode_mask))
2154 {
2155 case -2: report_file_error ("Copying permissions from", list1 (file));
2156 case -1: report_file_error ("Copying permissions to", list1 (newname));
2157 }
2178 } 2158 }
2179#endif /* not MSDOS */ 2159#endif /* not MSDOS */
2180 2160
@@ -2191,17 +2171,6 @@ entries (depending on how Emacs was built). */)
2191 } 2171 }
2192#endif 2172#endif
2193 2173
2194#ifdef HAVE_POSIX_ACL
2195 if (acl != NULL)
2196 {
2197 bool fail = acl_set_fd (ofd, acl) != 0;
2198 if (fail && !ACL_NOT_WELL_SUPPORTED (errno))
2199 report_file_error ("Setting ACL", Fcons (newname, Qnil));
2200
2201 acl_free (acl);
2202 }
2203#endif
2204
2205 if (!NILP (keep_time)) 2174 if (!NILP (keep_time))
2206 { 2175 {
2207 EMACS_TIME atime = get_stat_atime (&st); 2176 EMACS_TIME atime = get_stat_atime (&st);
@@ -3111,7 +3080,7 @@ was unable to determine the ACL entries. */)
3111{ 3080{
3112 Lisp_Object absname; 3081 Lisp_Object absname;
3113 Lisp_Object handler; 3082 Lisp_Object handler;
3114#ifdef HAVE_POSIX_ACL 3083#ifdef HAVE_ACL_SET_FILE
3115 acl_t acl; 3084 acl_t acl;
3116 Lisp_Object acl_string; 3085 Lisp_Object acl_string;
3117 char *str; 3086 char *str;
@@ -3126,7 +3095,7 @@ was unable to determine the ACL entries. */)
3126 if (!NILP (handler)) 3095 if (!NILP (handler))
3127 return call2 (handler, Qfile_acl, absname); 3096 return call2 (handler, Qfile_acl, absname);
3128 3097
3129#ifdef HAVE_POSIX_ACL 3098#ifdef HAVE_ACL_SET_FILE
3130 absname = ENCODE_FILE (absname); 3099 absname = ENCODE_FILE (absname);
3131 3100
3132 acl = acl_get_file (SSDATA (absname), ACL_TYPE_ACCESS); 3101 acl = acl_get_file (SSDATA (absname), ACL_TYPE_ACCESS);
@@ -3164,7 +3133,7 @@ support. */)
3164{ 3133{
3165 Lisp_Object absname; 3134 Lisp_Object absname;
3166 Lisp_Object handler; 3135 Lisp_Object handler;
3167#ifdef HAVE_POSIX_ACL 3136#ifdef HAVE_ACL_SET_FILE
3168 Lisp_Object encoded_absname; 3137 Lisp_Object encoded_absname;
3169 acl_t acl; 3138 acl_t acl;
3170 bool fail; 3139 bool fail;
@@ -3178,7 +3147,7 @@ support. */)
3178 if (!NILP (handler)) 3147 if (!NILP (handler))
3179 return call3 (handler, Qset_file_acl, absname, acl_string); 3148 return call3 (handler, Qset_file_acl, absname, acl_string);
3180 3149
3181#ifdef HAVE_POSIX_ACL 3150#ifdef HAVE_ACL_SET_FILE
3182 if (STRINGP (acl_string)) 3151 if (STRINGP (acl_string))
3183 { 3152 {
3184 acl = acl_from_text (SSDATA (acl_string)); 3153 acl = acl_from_text (SSDATA (acl_string));
@@ -3193,7 +3162,7 @@ support. */)
3193 fail = (acl_set_file (SSDATA (encoded_absname), ACL_TYPE_ACCESS, 3162 fail = (acl_set_file (SSDATA (encoded_absname), ACL_TYPE_ACCESS,
3194 acl) 3163 acl)
3195 != 0); 3164 != 0);
3196 if (fail && !ACL_NOT_WELL_SUPPORTED (errno)) 3165 if (fail && acl_errno_valid (errno))
3197 report_file_error ("Setting ACL", Fcons (absname, Qnil)); 3166 report_file_error ("Setting ACL", Fcons (absname, Qnil));
3198 3167
3199 acl_free (acl); 3168 acl_free (acl);
@@ -4979,15 +4948,14 @@ This calls `write-region-annotate-functions' at the start, and
4979 4948
4980 immediate_quit = 0; 4949 immediate_quit = 0;
4981 4950
4982 /* fsync appears to change the modtime on BSD4.2. 4951 /* fsync is not crucial for auto-save files, since they might lose
4983 Disk full in NFS may be reported here. */ 4952 some work anyway. */
4984 /* mib says that closing the file will try to write as fast as NFS can do
4985 it, and that means the fsync here is not crucial for autosave files. */
4986 if (!auto_saving && !write_region_inhibit_fsync) 4953 if (!auto_saving && !write_region_inhibit_fsync)
4987 { 4954 {
4988 /* Transfer data and metadata to disk, retrying if interrupted. Also, 4955 /* Transfer data and metadata to disk, retrying if interrupted.
4989 ignore EINVAL which happens when fsync is not supported on this 4956 fsync can report a write failure here, e.g., due to disk full
4990 file. */ 4957 under NFS. But ignore EINVAL, which means fsync is not
4958 supported on this file. */
4991 while (fsync (desc) != 0) 4959 while (fsync (desc) != 0)
4992 if (errno != EINTR) 4960 if (errno != EINTR)
4993 { 4961 {
@@ -6069,11 +6037,28 @@ in the buffer; this is the default behavior, because the auto-save
6069file is usually more useful if it contains the deleted text. */); 6037file is usually more useful if it contains the deleted text. */);
6070 Vauto_save_include_big_deletions = Qnil; 6038 Vauto_save_include_big_deletions = Qnil;
6071 6039
6040 /* fsync can be a significant performance hit. Often it doesn't
6041 suffice to make the file-save operation survive a crash. For
6042 batch scripts, which are typically part of larger shell commands
6043 that don't fsync other files, its effect on performance can be
6044 significant so its utility is particularly questionable.
6045 Hence, for now by default fsync is used only when interactive.
6046
6047 For more on why fsync often fails to work on today's hardware, see:
6048 Zheng M et al. Understanding the robustness of SSDs under power fault.
6049 11th USENIX Conf. on File and Storage Technologies, 2013 (FAST '13), 271-84
6050 http://www.usenix.org/system/files/conference/fast13/fast13-final80.pdf
6051
6052 For more on why fsync does not suffice even if it works properly, see:
6053 Roche X. Necessary step(s) to synchronize filename operations on disk.
6054 Austin Group Defect 672, 2013-03-19
6055 http://austingroupbugs.net/view.php?id=672 */
6072 DEFVAR_BOOL ("write-region-inhibit-fsync", write_region_inhibit_fsync, 6056 DEFVAR_BOOL ("write-region-inhibit-fsync", write_region_inhibit_fsync,
6073 doc: /* Non-nil means don't call fsync in `write-region'. 6057 doc: /* Non-nil means don't call fsync in `write-region'.
6074This variable affects calls to `write-region' as well as save commands. 6058This variable affects calls to `write-region' as well as save commands.
6075A non-nil value may result in data loss! */); 6059Setting this to nil may avoid data loss if the system loses power or
6076 write_region_inhibit_fsync = 0; 6060the operating system crashes. */);
6061 write_region_inhibit_fsync = noninteractive;
6077 6062
6078 DEFVAR_BOOL ("delete-by-moving-to-trash", delete_by_moving_to_trash, 6063 DEFVAR_BOOL ("delete-by-moving-to-trash", delete_by_moving_to_trash,
6079 doc: /* Specifies whether to use the system's trash can. 6064 doc: /* Specifies whether to use the system's trash can.
diff --git a/src/filelock.c b/src/filelock.c
index f17d3182eab..de6aba8385c 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -437,14 +437,8 @@ create_lock_file (char *lfname, char *lock_info_str, bool force)
437 if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len 437 if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len
438 || (need_fchmod && fchmod (fd, world_readable) != 0)) 438 || (need_fchmod && fchmod (fd, world_readable) != 0))
439 err = errno; 439 err = errno;
440 else 440 /* There is no need to call fsync here, as the contents of
441 while (fsync (fd) != 0) 441 the lock file need not survive system crashes. */
442 if (errno != EINTR)
443 {
444 if (errno != EINVAL)
445 err = errno;
446 break;
447 }
448 if (emacs_close (fd) != 0) 442 if (emacs_close (fd) != 0)
449 err = errno; 443 err = errno;
450 if (!err && rename_lock_file (nonce, lfname, force) != 0) 444 if (!err && rename_lock_file (nonce, lfname, force) != 0)
diff --git a/src/gtkutil.c b/src/gtkutil.c
index f83d8660fcc..8ac58f18158 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -70,13 +70,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
70#define gtk_adjustment_get_step_increment(w) ((w)->step_increment) 70#define gtk_adjustment_get_step_increment(w) ((w)->step_increment)
71#define gtk_adjustment_set_step_increment(w, s) ((w)->step_increment = (s)) 71#define gtk_adjustment_set_step_increment(w, s) ((w)->step_increment = (s))
72#endif 72#endif
73#if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 11 73#if GTK_CHECK_VERSION (2, 12, 0)
74#define remove_submenu(w) gtk_menu_item_set_submenu ((w), NULL) 74#define remove_submenu(w) gtk_menu_item_set_submenu ((w), NULL)
75#else 75#else
76#define remove_submenu(w) gtk_menu_item_remove_submenu ((w)) 76#define remove_submenu(w) gtk_menu_item_remove_submenu ((w))
77#endif 77#endif
78 78
79#if GTK_MAJOR_VERSION > 3 || (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION >= 2) 79#if GTK_CHECK_VERSION (3, 2, 0)
80#define USE_NEW_GTK_FONT_CHOOSER 1 80#define USE_NEW_GTK_FONT_CHOOSER 1
81#else 81#else
82#define USE_NEW_GTK_FONT_CHOOSER 0 82#define USE_NEW_GTK_FONT_CHOOSER 0
@@ -202,7 +202,7 @@ xg_display_close (Display *dpy)
202 gdpy_def = gdpy_new; 202 gdpy_def = gdpy_new;
203 } 203 }
204 204
205#if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 10 205#if GTK_CHECK_VERSION (2, 0, 0) && ! GTK_CHECK_VERSION (2, 10, 0)
206 /* GTK 2.2-2.8 has a bug that makes gdk_display_close crash (bug 206 /* GTK 2.2-2.8 has a bug that makes gdk_display_close crash (bug
207 http://bugzilla.gnome.org/show_bug.cgi?id=85715). This way we 207 http://bugzilla.gnome.org/show_bug.cgi?id=85715). This way we
208 can continue running, but there will be memory leaks. */ 208 can continue running, but there will be memory leaks. */
@@ -1155,7 +1155,8 @@ xg_create_frame_widgets (FRAME_PTR f)
1155 has backported it to Gtk+ 2.0 and they add the resize grip for 1155 has backported it to Gtk+ 2.0 and they add the resize grip for
1156 Gtk+ 2.0 applications also. But it has a bug that makes Emacs loop 1156 Gtk+ 2.0 applications also. But it has a bug that makes Emacs loop
1157 forever, so disable the grip. */ 1157 forever, so disable the grip. */
1158#if GTK_MAJOR_VERSION < 3 && defined (HAVE_GTK_WINDOW_SET_HAS_RESIZE_GRIP) 1158#if (! GTK_CHECK_VERSION (3, 0, 0) \
1159 && defined HAVE_GTK_WINDOW_SET_HAS_RESIZE_GRIP)
1159 gtk_window_set_has_resize_grip (GTK_WINDOW (wtop), FALSE); 1160 gtk_window_set_has_resize_grip (GTK_WINDOW (wtop), FALSE);
1160#endif 1161#endif
1161 1162
diff --git a/src/image.c b/src/image.c
index 2dae63a294f..f9f6ce70040 100644
--- a/src/image.c
+++ b/src/image.c
@@ -7263,6 +7263,25 @@ gif_load (struct frame *f, struct image *img)
7263 return 0; 7263 return 0;
7264 } 7264 }
7265 7265
7266 /* Check that the selected subimages fit. It's not clear whether
7267 the GIF spec requires this, but Emacs can crash if they don't fit. */
7268 for (j = 0; j <= idx; ++j)
7269 {
7270 struct SavedImage *subimage = gif->SavedImages + j;
7271 int subimg_width = subimage->ImageDesc.Width;
7272 int subimg_height = subimage->ImageDesc.Height;
7273 int subimg_top = subimage->ImageDesc.Top;
7274 int subimg_left = subimage->ImageDesc.Left;
7275 if (! (0 <= subimg_width && 0 <= subimg_height
7276 && 0 <= subimg_top && subimg_top <= height - subimg_height
7277 && 0 <= subimg_left && subimg_left <= width - subimg_width))
7278 {
7279 image_error ("Subimage does not fit in image", Qnil, Qnil);
7280 fn_DGifCloseFile (gif);
7281 return 0;
7282 }
7283 }
7284
7266 /* Create the X image and pixmap. */ 7285 /* Create the X image and pixmap. */
7267 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) 7286 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7268 { 7287 {
diff --git a/src/lread.c b/src/lread.c
index 8e623e838c7..15821662fc8 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -201,6 +201,9 @@ readchar (Lisp_Object readcharfun, bool *multibyte)
201 201
202 ptrdiff_t pt_byte = BUF_PT_BYTE (inbuffer); 202 ptrdiff_t pt_byte = BUF_PT_BYTE (inbuffer);
203 203
204 if (! BUFFER_LIVE_P (inbuffer))
205 return -1;
206
204 if (pt_byte >= BUF_ZV_BYTE (inbuffer)) 207 if (pt_byte >= BUF_ZV_BYTE (inbuffer))
205 return -1; 208 return -1;
206 209
@@ -375,6 +378,19 @@ skip_dyn_bytes (Lisp_Object readcharfun, ptrdiff_t n)
375 } 378 }
376} 379}
377 380
381static void
382skip_dyn_eof (Lisp_Object readcharfun)
383{
384 if (FROM_FILE_P (readcharfun))
385 {
386 block_input (); /* FIXME: Not sure if it's needed. */
387 fseek (instream, 0, SEEK_END);
388 unblock_input ();
389 }
390 else
391 while (READCHAR >= 0);
392}
393
378/* Unread the character C in the way appropriate for the stream READCHARFUN. 394/* Unread the character C in the way appropriate for the stream READCHARFUN.
379 If the stream is a user function, call it with the char as argument. */ 395 If the stream is a user function, call it with the char as argument. */
380 396
@@ -1976,7 +1992,9 @@ STREAM or the value of `standard-input' may be:
1976 if (EQ (stream, Qt)) 1992 if (EQ (stream, Qt))
1977 stream = Qread_char; 1993 stream = Qread_char;
1978 if (EQ (stream, Qread_char)) 1994 if (EQ (stream, Qread_char))
1979 return Fread_minibuffer (build_string ("Lisp expression: "), Qnil); 1995 /* FIXME: ¿¡ When is this used !? */
1996 return call1 (intern ("read-minibuffer"),
1997 build_string ("Lisp expression: "));
1980 1998
1981 return read_internal_start (stream, Qnil, Qnil); 1999 return read_internal_start (stream, Qnil, Qnil);
1982} 2000}
@@ -2617,7 +2635,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2617 if (c == '@') 2635 if (c == '@')
2618 { 2636 {
2619 enum { extra = 100 }; 2637 enum { extra = 100 };
2620 ptrdiff_t i, nskip = 0; 2638 ptrdiff_t i, nskip = 0, digits = 0;
2621 2639
2622 /* Read a decimal integer. */ 2640 /* Read a decimal integer. */
2623 while ((c = READCHAR) >= 0 2641 while ((c = READCHAR) >= 0
@@ -2625,8 +2643,14 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2625 { 2643 {
2626 if ((STRING_BYTES_BOUND - extra) / 10 <= nskip) 2644 if ((STRING_BYTES_BOUND - extra) / 10 <= nskip)
2627 string_overflow (); 2645 string_overflow ();
2646 digits++;
2628 nskip *= 10; 2647 nskip *= 10;
2629 nskip += c - '0'; 2648 nskip += c - '0';
2649 if (digits == 2 && nskip == 0)
2650 { /* We've just seen #@00, which means "skip to end". */
2651 skip_dyn_eof (readcharfun);
2652 return Qnil;
2653 }
2630 } 2654 }
2631 if (nskip > 0) 2655 if (nskip > 0)
2632 /* We can't use UNREAD here, because in the code below we side-step 2656 /* We can't use UNREAD here, because in the code below we side-step
diff --git a/src/makefile.w32-in b/src/makefile.w32-in
index aacc258cd11..3484d6c70c8 100644
--- a/src/makefile.w32-in
+++ b/src/makefile.w32-in
@@ -388,6 +388,9 @@ EMACS_ROOT = ..
388GNU_LIB = $(EMACS_ROOT)/lib 388GNU_LIB = $(EMACS_ROOT)/lib
389NT_INC = $(EMACS_ROOT)/nt/inc 389NT_INC = $(EMACS_ROOT)/nt/inc
390 390
391ACL_H = $(GNU_LIB)/acl.h \
392 $(NT_INC)/sys/stat.h \
393 $(NT_INC)/stdbool.h
391SYSTIME_H = $(SRC)/systime.h \ 394SYSTIME_H = $(SRC)/systime.h \
392 $(NT_INC)/sys/time.h \ 395 $(NT_INC)/sys/time.h \
393 $(GNU_LIB)/timespec.h 396 $(GNU_LIB)/timespec.h
@@ -848,6 +851,7 @@ $(BLD)/fileio.$(O) : \
848 $(NT_INC)/sys/stat.h \ 851 $(NT_INC)/sys/stat.h \
849 $(NT_INC)/unistd.h \ 852 $(NT_INC)/unistd.h \
850 $(GNU_LIB)/allocator.h \ 853 $(GNU_LIB)/allocator.h \
854 $(ACL_H) \
851 $(BUFFER_H) \ 855 $(BUFFER_H) \
852 $(CAREADLINKAT_H) \ 856 $(CAREADLINKAT_H) \
853 $(CHARACTER_H) \ 857 $(CHARACTER_H) \
diff --git a/src/minibuf.c b/src/minibuf.c
index b96d27e0742..b69a16eff42 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -986,34 +986,6 @@ and some related functions, which use zero-indexing for POSITION. */)
986 return val; 986 return val;
987} 987}
988 988
989DEFUN ("read-minibuffer", Fread_minibuffer, Sread_minibuffer, 1, 2, 0,
990 doc: /* Return a Lisp object read using the minibuffer, unevaluated.
991Prompt with PROMPT. If non-nil, optional second arg INITIAL-CONTENTS
992is a string to insert in the minibuffer before reading.
993\(INITIAL-CONTENTS can also be a cons of a string and an integer.
994Such arguments are used as in `read-from-minibuffer'.) */)
995 (Lisp_Object prompt, Lisp_Object initial_contents)
996{
997 CHECK_STRING (prompt);
998 return read_minibuf (Vminibuffer_local_map, initial_contents,
999 prompt, 1, Qminibuffer_history,
1000 make_number (0), Qnil, 0, 0);
1001}
1002
1003DEFUN ("eval-minibuffer", Feval_minibuffer, Seval_minibuffer, 1, 2, 0,
1004 doc: /* Return value of Lisp expression read using the minibuffer.
1005Prompt with PROMPT. If non-nil, optional second arg INITIAL-CONTENTS
1006is a string to insert in the minibuffer before reading.
1007\(INITIAL-CONTENTS can also be a cons of a string and an integer.
1008Such arguments are used as in `read-from-minibuffer'.) */)
1009 (Lisp_Object prompt, Lisp_Object initial_contents)
1010{
1011 return Feval (read_minibuf (Vread_expression_map, initial_contents,
1012 prompt, 1, Qread_expression_history,
1013 make_number (0), Qnil, 0, 0),
1014 Qnil);
1015}
1016
1017/* Functions that use the minibuffer to read various things. */ 989/* Functions that use the minibuffer to read various things. */
1018 990
1019DEFUN ("read-string", Fread_string, Sread_string, 1, 5, 0, 991DEFUN ("read-string", Fread_string, Sread_string, 1, 5, 0,
@@ -2137,15 +2109,9 @@ properties. */);
2137 Vminibuffer_prompt_properties 2109 Vminibuffer_prompt_properties
2138 = Fcons (intern_c_string ("read-only"), Fcons (Qt, Qnil)); 2110 = Fcons (intern_c_string ("read-only"), Fcons (Qt, Qnil));
2139 2111
2140 DEFVAR_LISP ("read-expression-map", Vread_expression_map,
2141 doc: /* Minibuffer keymap used for reading Lisp expressions. */);
2142 Vread_expression_map = Qnil;
2143
2144 defsubr (&Sactive_minibuffer_window); 2112 defsubr (&Sactive_minibuffer_window);
2145 defsubr (&Sset_minibuffer_window); 2113 defsubr (&Sset_minibuffer_window);
2146 defsubr (&Sread_from_minibuffer); 2114 defsubr (&Sread_from_minibuffer);
2147 defsubr (&Seval_minibuffer);
2148 defsubr (&Sread_minibuffer);
2149 defsubr (&Sread_string); 2115 defsubr (&Sread_string);
2150 defsubr (&Sread_command); 2116 defsubr (&Sread_command);
2151 defsubr (&Sread_variable); 2117 defsubr (&Sread_variable);
diff --git a/src/nsfns.m b/src/nsfns.m
index 0d9ebe0ef50..497a856aa10 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -44,6 +44,10 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
44#include "fontset.h" 44#include "fontset.h"
45#include "font.h" 45#include "font.h"
46 46
47#ifdef NS_IMPL_COCOA
48#include <IOKit/graphics/IOGraphicsLib.h>
49#endif
50
47#if 0 51#if 0
48int fns_trace_num = 1; 52int fns_trace_num = 1;
49#define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \ 53#define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \
@@ -101,6 +105,8 @@ static int as_status;
101static ptrdiff_t image_cache_refcount; 105static ptrdiff_t image_cache_refcount;
102#endif 106#endif
103 107
108static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource;
109
104/* ========================================================================== 110/* ==========================================================================
105 111
106 Internal utility functions 112 Internal utility functions
@@ -1502,7 +1508,7 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */)
1502 1508
1503 ret = (ret == NSOKButton) || panelOK; 1509 ret = (ret == NSOKButton) || panelOK;
1504 1510
1505 if (ret) 1511 if (ret)
1506 { 1512 {
1507 NSString *str = [panel getFilename]; 1513 NSString *str = [panel getFilename];
1508 if (! str) str = [panel getDirectory]; 1514 if (! str) str = [panel getDirectory];
@@ -1699,7 +1705,7 @@ If omitted or nil, the selected frame's display is used. */)
1699 (Lisp_Object display) 1705 (Lisp_Object display)
1700{ 1706{
1701 NSWindowDepth depth; 1707 NSWindowDepth depth;
1702 1708
1703 check_ns_display_info (display); 1709 check_ns_display_info (display);
1704 depth = [ns_get_screen (display) depth]; 1710 depth = [ns_get_screen (display) depth];
1705 1711
@@ -2267,7 +2273,7 @@ DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
2267{ 2273{
2268 NSWindowDepth depth; 2274 NSWindowDepth depth;
2269 NSString *colorSpace; 2275 NSString *colorSpace;
2270 2276
2271 check_ns_display_info (display); 2277 check_ns_display_info (display);
2272 depth = [ns_get_screen (display) depth]; 2278 depth = [ns_get_screen (display) depth];
2273 colorSpace = NSColorSpaceFromDepth (depth); 2279 colorSpace = NSColorSpaceFromDepth (depth);
@@ -2321,35 +2327,221 @@ If omitted or nil, that stands for the selected frame's display. */)
2321 return make_number ((int) [ns_get_screen (display) frame].size.height); 2327 return make_number ((int) [ns_get_screen (display) frame].size.height);
2322} 2328}
2323 2329
2330struct MonitorInfo {
2331 XRectangle geom, work;
2332 int mm_width, mm_height;
2333 char *name;
2334};
2324 2335
2325DEFUN ("display-usable-bounds", Fns_display_usable_bounds, 2336static void
2326 Sns_display_usable_bounds, 0, 1, 0, 2337free_monitors (struct MonitorInfo *monitors, int n_monitors)
2327 doc: /* Return the bounds of the usable part of the screen. 2338{
2328The return value is a list of integers (LEFT TOP WIDTH HEIGHT), which 2339 int i;
2329are the boundaries of the usable part of the screen, excluding areas 2340 for (i = 0; i < n_monitors; ++i)
2330reserved for the Mac menu, dock, and so forth. 2341 xfree (monitors[i].name);
2342 xfree (monitors);
2343}
2331 2344
2332The screen queried corresponds to DISPLAY, which should be either a 2345#ifdef NS_IMPL_COCOA
2333frame, a display name (a string), or terminal ID. If omitted or nil, 2346/* Returns the name for the screen that DICT came from, or NULL.
2334that stands for the selected frame's display. */) 2347 Caller must free return value.
2335 (Lisp_Object display) 2348*/
2349
2350char *
2351ns_screen_name (CGDirectDisplayID did)
2352{
2353 char *name = NULL;
2354 NSDictionary *info = (NSDictionary *)
2355 IODisplayCreateInfoDictionary (CGDisplayIOServicePort (did),
2356 kIODisplayOnlyPreferredName);
2357 NSDictionary *names
2358 = [info objectForKey:
2359 [NSString stringWithUTF8String:kDisplayProductName]];
2360
2361 if ([names count] > 0) {
2362 NSString *n = [names objectForKey: [[names allKeys] objectAtIndex:0]];
2363 if (n != nil)
2364 name = xstrdup ([n UTF8String]);
2365 }
2366
2367 [info release];
2368 return name;
2369}
2370#endif
2371
2372static Lisp_Object
2373ns_make_monitor_attribute_list (struct MonitorInfo *monitors,
2374 int n_monitors,
2375 int primary_monitor,
2376 const char *source)
2377{
2378 Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
2379 Lisp_Object frame, rest, attributes_list = Qnil;
2380 Lisp_Object primary_monitor_attributes = Qnil;
2381 NSArray *screens = [NSScreen screens];
2382 int i;
2383
2384 FOR_EACH_FRAME (rest, frame)
2385 {
2386 struct frame *f = XFRAME (frame);
2387
2388 if (FRAME_NS_P (f))
2389 {
2390 NSView *view = FRAME_NS_VIEW (f);
2391 NSScreen *screen = [[view window] screen];
2392 NSUInteger k;
2393
2394 i = -1;
2395 for (k = 0; i == -1 && k < [screens count]; ++k)
2396 {
2397 if ([screens objectAtIndex: k] == screen)
2398 i = (int)k;
2399 }
2400
2401 if (i > -1)
2402 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
2403 }
2404 }
2405
2406 for (i = 0; i < n_monitors; ++i)
2407 {
2408 Lisp_Object geometry, workarea, attributes = Qnil;
2409 struct MonitorInfo *mi = &monitors[i];
2410
2411 if (mi->geom.width == 0) continue;
2412
2413 workarea = list4i (mi->work.x, mi->work.y,
2414 mi->work.width, mi->work.height);
2415 geometry = list4i (mi->geom.x, mi->geom.y,
2416 mi->geom.width, mi->geom.height);
2417 attributes = Fcons (Fcons (Qsource,
2418 make_string (source, strlen (source))),
2419 attributes);
2420 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
2421 attributes);
2422 attributes = Fcons (Fcons (Qmm_size,
2423 list2i (mi->mm_width, mi->mm_height)),
2424 attributes);
2425 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
2426 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
2427 if (mi->name)
2428 attributes = Fcons (Fcons (Qname, make_string (mi->name,
2429 strlen (mi->name))),
2430 attributes);
2431
2432 if (i == primary_monitor)
2433 primary_monitor_attributes = attributes;
2434 else
2435 attributes_list = Fcons (attributes, attributes_list);
2436 }
2437
2438 if (!NILP (primary_monitor_attributes))
2439 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
2440 return attributes_list;
2441}
2442
2443DEFUN ("ns-display-monitor-attributes-list",
2444 Fns_display_monitor_attributes_list,
2445 Sns_display_monitor_attributes_list,
2446 0, 1, 0,
2447 doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
2448
2449The optional argument TERMINAL specifies which display to ask about.
2450TERMINAL should be a terminal object, a frame or a display name (a string).
2451If omitted or nil, that stands for the selected frame's display.
2452
2453In addition to the standard attribute keys listed in
2454`display-monitor-attributes-list', the following keys are contained in
2455the attributes:
2456
2457 source -- String describing the source from which multi-monitor
2458 information is obtained, \"NS\" is always the source."
2459
2460Internal use only, use `display-monitor-attributes-list' instead. */)
2461 (Lisp_Object terminal)
2336{ 2462{
2337 NSScreen *screen; 2463 struct terminal *term = get_terminal (terminal, 1);
2338 NSRect vScreen; 2464 NSArray *screens;
2465 NSUInteger i, n_monitors;
2466 struct MonitorInfo *monitors;
2467 Lisp_Object attributes_list = Qnil;
2468 CGFloat primary_display_height = 0;
2339 2469
2340 check_ns_display_info (display); 2470 if (term->type != output_ns)
2341 screen = ns_get_screen (display);
2342 if (!screen)
2343 return Qnil; 2471 return Qnil;
2344 2472
2345 vScreen = [screen visibleFrame]; 2473 screens = [NSScreen screens];
2474 n_monitors = [screens count];
2475 if (n_monitors == 0)
2476 return Qnil;
2477
2478 monitors = (struct MonitorInfo *) xzalloc (n_monitors * sizeof (*monitors));
2479
2480 for (i = 0; i < [screens count]; ++i)
2481 {
2482 NSScreen *s = [screens objectAtIndex:i];
2483 struct MonitorInfo *m = &monitors[i];
2484 NSRect fr = [s frame];
2485 NSRect vfr = [s visibleFrame];
2486 NSDictionary *dict = [s deviceDescription];
2487 NSValue *resval = [dict valueForKey:NSDeviceResolution];
2488 short y, vy;
2489
2490#ifdef NS_IMPL_COCOA
2491 NSNumber *nid = [dict objectForKey:@"NSScreenNumber"];
2492 CGDirectDisplayID did = [nid unsignedIntValue];
2493#endif
2494 if (i == 0)
2495 {
2496 primary_display_height = fr.size.height;
2497 y = (short) fr.origin.y;
2498 vy = (short) vfr.origin.y;
2499 }
2500 else
2501 {
2502 // Flip y coordinate as NS has y starting from the bottom.
2503 y = (short) (primary_display_height - fr.size.height - fr.origin.y);
2504 vy = (short) (primary_display_height -
2505 vfr.size.height - vfr.origin.y);
2506 }
2507
2508 m->geom.x = (short) fr.origin.x;
2509 m->geom.y = y;
2510 m->geom.width = (unsigned short) fr.size.width;
2511 m->geom.height = (unsigned short) fr.size.height;
2512
2513 m->work.x = (short) vfr.origin.x;
2514 // y is flipped on NS, so vy - y are pixels missing at the bottom,
2515 // and fr.size.height - vfr.size.height are pixels missing in total.
2516 // Pixels missing at top are
2517 // fr.size.height - vfr.size.height - vy + y.
2518 // work.y is then pixels missing at top + y.
2519 m->work.y = (short) (fr.size.height - vfr.size.height) - vy + y + y;
2520 m->work.width = (unsigned short) vfr.size.width;
2521 m->work.height = (unsigned short) vfr.size.height;
2522
2523#ifdef NS_IMPL_COCOA
2524 m->name = ns_screen_name (did);
2525
2526 {
2527 CGSize mms = CGDisplayScreenSize (did);
2528 m->mm_width = (int) mms.width;
2529 m->mm_height = (int) mms.height;
2530 }
2531
2532#else
2533 // Assume 92 dpi as x-display-mm-height/x-display-mm-width does.
2534 m->mm_width = (int) (25.4 * fr.size.width / 92.0);
2535 m->mm_height = (int) (25.4 * fr.size.height / 92.0);
2536#endif
2537 }
2538
2539 // Primary monitor is always first for NS.
2540 attributes_list = ns_make_monitor_attribute_list (monitors, n_monitors,
2541 0, "NS");
2346 2542
2347 /* NS coordinate system is upside-down. 2543 free_monitors (monitors, n_monitors);
2348 Transform to screen-specific coordinates. */ 2544 return attributes_list;
2349 return list4i (vScreen.origin.x,
2350 [screen frame].size.height
2351 - vScreen.size.height - vScreen.origin.y,
2352 vScreen.size.width, vScreen.size.height);
2353} 2545}
2354 2546
2355 2547
@@ -2546,7 +2738,7 @@ Value is t if tooltip was open, nil otherwise. */)
2546 2738
2547/* 2739/*
2548 Handle arrow/function/control keys and copy/paste/cut in file dialogs. 2740 Handle arrow/function/control keys and copy/paste/cut in file dialogs.
2549 Return YES if handeled, NO if not. 2741 Return YES if handled, NO if not.
2550 */ 2742 */
2551static BOOL 2743static BOOL
2552handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent) 2744handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
@@ -2729,6 +2921,11 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
2729void 2921void
2730syms_of_nsfns (void) 2922syms_of_nsfns (void)
2731{ 2923{
2924 DEFSYM (Qgeometry, "geometry");
2925 DEFSYM (Qworkarea, "workarea");
2926 DEFSYM (Qmm_size, "mm-size");
2927 DEFSYM (Qframes, "frames");
2928 DEFSYM (Qsource, "source");
2732 Qfontsize = intern_c_string ("fontsize"); 2929 Qfontsize = intern_c_string ("fontsize");
2733 staticpro (&Qfontsize); 2930 staticpro (&Qfontsize);
2734 2931
@@ -2774,7 +2971,7 @@ be used as the image of the icon representing the frame. */);
2774 defsubr (&Sx_server_version); 2971 defsubr (&Sx_server_version);
2775 defsubr (&Sx_display_pixel_width); 2972 defsubr (&Sx_display_pixel_width);
2776 defsubr (&Sx_display_pixel_height); 2973 defsubr (&Sx_display_pixel_height);
2777 defsubr (&Sns_display_usable_bounds); 2974 defsubr (&Sns_display_monitor_attributes_list);
2778 defsubr (&Sx_display_mm_width); 2975 defsubr (&Sx_display_mm_width);
2779 defsubr (&Sx_display_mm_height); 2976 defsubr (&Sx_display_mm_height);
2780 defsubr (&Sx_display_screens); 2977 defsubr (&Sx_display_screens);
diff --git a/src/nsfont.m b/src/nsfont.m
index ebee363651f..9ab369d1fcd 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -151,10 +151,13 @@ ns_spec_to_descriptor (Lisp_Object font_spec)
151 if ([tdict count] > 0) 151 if ([tdict count] > 0)
152 [fdAttrs setObject: tdict forKey: NSFontTraitsAttribute]; 152 [fdAttrs setObject: tdict forKey: NSFontTraitsAttribute];
153 153
154 fdesc = [NSFontDescriptor fontDescriptorWithFontAttributes: fdAttrs]; 154 fdesc = [[[NSFontDescriptor fontDescriptorWithFontAttributes: fdAttrs]
155 retain] autorelease];
156
155 if (family != nil) 157 if (family != nil)
156 { 158 {
157 fdesc = [fdesc fontDescriptorWithFamily: family]; 159 NSFontDescriptor *fdesc2 = [fdesc fontDescriptorWithFamily: family];
160 fdesc = [[fdesc2 retain] autorelease];
158 } 161 }
159 162
160 [fdAttrs release]; 163 [fdAttrs release];
diff --git a/src/nsmenu.m b/src/nsmenu.m
index 648b568d180..baa683941f8 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -119,7 +119,6 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu)
119 id menu = [NSApp mainMenu]; 119 id menu = [NSApp mainMenu];
120 static EmacsMenu *last_submenu = nil; 120 static EmacsMenu *last_submenu = nil;
121 BOOL needsSet = NO; 121 BOOL needsSet = NO;
122 const char *submenuTitle = [[submenu title] UTF8String];
123 bool owfi; 122 bool owfi;
124 Lisp_Object items; 123 Lisp_Object items;
125 widget_value *wv, *first_wv, *prev_wv = 0; 124 widget_value *wv, *first_wv, *prev_wv = 0;
@@ -239,7 +238,7 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu)
239 /* FIXME: we'd like to only parse the needed submenu, but this 238 /* FIXME: we'd like to only parse the needed submenu, but this
240 was causing crashes in the _common parsing code.. need to make 239 was causing crashes in the _common parsing code.. need to make
241 sure proper initialization done.. */ 240 sure proper initialization done.. */
242/* if (submenu && strcmp (submenuTitle, SSDATA (string))) 241/* if (submenu && strcmp ([[submenu title] UTF8String], SSDATA (string)))
243 continue; */ 242 continue; */
244 243
245 submenu_start[i] = menu_items_used; 244 submenu_start[i] = menu_items_used;
@@ -259,7 +258,7 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu)
259 { 258 {
260 /* should have found a menu for this one but didn't */ 259 /* should have found a menu for this one but didn't */
261 fprintf (stderr, "ERROR: did not find lisp menu for submenu '%s'.\n", 260 fprintf (stderr, "ERROR: did not find lisp menu for submenu '%s'.\n",
262 submenuTitle); 261 [[submenu title] UTF8String]);
263 discard_menu_items (); 262 discard_menu_items ();
264 unbind_to (specpdl_count, Qnil); 263 unbind_to (specpdl_count, Qnil);
265 [pool release]; 264 [pool release];
@@ -346,8 +345,6 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu)
346 string = AREF (items, i + 1); 345 string = AREF (items, i + 1);
347 if (NILP (string)) 346 if (NILP (string))
348 break; 347 break;
349/* if (submenu && strcmp (submenuTitle, SSDATA (string)))
350 continue; */
351 348
352 wv->name = SSDATA (string); 349 wv->name = SSDATA (string);
353 update_submenu_strings (wv->contents); 350 update_submenu_strings (wv->contents);
@@ -358,6 +355,7 @@ ns_update_menubar (struct frame *f, bool deep_p, EmacsMenu *submenu)
358 create a new menu for each sub and fill it. */ 355 create a new menu for each sub and fill it. */
359 if (submenu) 356 if (submenu)
360 { 357 {
358 const char *submenuTitle = [[submenu title] UTF8String];
361 for (wv = first_wv->contents; wv; wv = wv->next) 359 for (wv = first_wv->contents; wv; wv = wv->next)
362 { 360 {
363 if (!strcmp (submenuTitle, wv->name)) 361 if (!strcmp (submenuTitle, wv->name))
diff --git a/src/regex.c b/src/regex.c
index 648f2529649..04429386f84 100644
--- a/src/regex.c
+++ b/src/regex.c
@@ -710,51 +710,27 @@ typedef enum
710 at SOURCE. */ 710 at SOURCE. */
711 711
712#define EXTRACT_NUMBER(destination, source) \ 712#define EXTRACT_NUMBER(destination, source) \
713 do { \ 713 ((destination) = extract_number (source))
714 (destination) = *(source) & 0377; \
715 (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \
716 } while (0)
717 714
718#ifdef DEBUG 715static int
719static void 716extract_number (re_char *source)
720extract_number (int *dest, re_char *source)
721{ 717{
722 int temp = SIGN_EXTEND_CHAR (*(source + 1)); 718 return (SIGN_EXTEND_CHAR (source[1]) << 8) + source[0];
723 *dest = *source & 0377;
724 *dest += temp << 8;
725} 719}
726 720
727# ifndef EXTRACT_MACROS /* To debug the macros. */
728# undef EXTRACT_NUMBER
729# define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
730# endif /* not EXTRACT_MACROS */
731
732#endif /* DEBUG */
733
734/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. 721/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
735 SOURCE must be an lvalue. */ 722 SOURCE must be an lvalue. */
736 723
737#define EXTRACT_NUMBER_AND_INCR(destination, source) \ 724#define EXTRACT_NUMBER_AND_INCR(destination, source) \
738 do { \ 725 ((destination) = extract_number_and_incr (&source))
739 EXTRACT_NUMBER (destination, source); \
740 (source) += 2; \
741 } while (0)
742 726
743#ifdef DEBUG 727static int
744static void 728extract_number_and_incr (re_char **source)
745extract_number_and_incr (int *destination, re_char **source)
746{ 729{
747 extract_number (destination, *source); 730 int num = extract_number (*source);
748 *source += 2; 731 *source += 2;
732 return num;
749} 733}
750
751# ifndef EXTRACT_MACROS
752# undef EXTRACT_NUMBER_AND_INCR
753# define EXTRACT_NUMBER_AND_INCR(dest, src) \
754 extract_number_and_incr (&dest, &src)
755# endif /* not EXTRACT_MACROS */
756
757#endif /* DEBUG */
758 734
759/* Store a multibyte character in three contiguous bytes starting 735/* Store a multibyte character in three contiguous bytes starting
760 DESTINATION, and increment DESTINATION to the byte after where the 736 DESTINATION, and increment DESTINATION to the byte after where the
@@ -861,10 +837,8 @@ extract_number_and_incr (int *destination, re_char **source)
861static int debug = -100000; 837static int debug = -100000;
862 838
863# define DEBUG_STATEMENT(e) e 839# define DEBUG_STATEMENT(e) e
864# define DEBUG_PRINT1(x) if (debug > 0) printf (x) 840# define DEBUG_PRINT(...) if (debug > 0) printf (__VA_ARGS__)
865# define DEBUG_PRINT2(x1, x2) if (debug > 0) printf (x1, x2) 841# define DEBUG_COMPILES_ARGUMENTS
866# define DEBUG_PRINT3(x1, x2, x3) if (debug > 0) printf (x1, x2, x3)
867# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug > 0) printf (x1, x2, x3, x4)
868# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ 842# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
869 if (debug > 0) print_partial_compiled_pattern (s, e) 843 if (debug > 0) print_partial_compiled_pattern (s, e)
870# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ 844# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
@@ -873,9 +847,8 @@ static int debug = -100000;
873 847
874/* Print the fastmap in human-readable form. */ 848/* Print the fastmap in human-readable form. */
875 849
876void 850static void
877print_fastmap (fastmap) 851print_fastmap (char *fastmap)
878 char *fastmap;
879{ 852{
880 unsigned was_a_range = 0; 853 unsigned was_a_range = 0;
881 unsigned i = 0; 854 unsigned i = 0;
@@ -905,10 +878,8 @@ print_fastmap (fastmap)
905/* Print a compiled pattern string in human-readable form, starting at 878/* Print a compiled pattern string in human-readable form, starting at
906 the START pointer into it and ending just before the pointer END. */ 879 the START pointer into it and ending just before the pointer END. */
907 880
908void 881static void
909print_partial_compiled_pattern (start, end) 882print_partial_compiled_pattern (re_char *start, re_char *end)
910 re_char *start;
911 re_char *end;
912{ 883{
913 int mcnt, mcnt2; 884 int mcnt, mcnt2;
914 re_char *p = start; 885 re_char *p = start;
@@ -923,7 +894,7 @@ print_partial_compiled_pattern (start, end)
923 /* Loop over pattern commands. */ 894 /* Loop over pattern commands. */
924 while (p < pend) 895 while (p < pend)
925 { 896 {
926 fprintf (stderr, "%d:\t", p - start); 897 fprintf (stderr, "%td:\t", p - start);
927 898
928 switch ((re_opcode_t) *p++) 899 switch ((re_opcode_t) *p++)
929 { 900 {
@@ -1027,51 +998,58 @@ print_partial_compiled_pattern (start, end)
1027 break; 998 break;
1028 999
1029 case on_failure_jump: 1000 case on_failure_jump:
1030 extract_number_and_incr (&mcnt, &p); 1001 EXTRACT_NUMBER_AND_INCR (mcnt, p);
1031 fprintf (stderr, "/on_failure_jump to %d", p + mcnt - start); 1002 fprintf (stderr, "/on_failure_jump to %td", p + mcnt - start);
1032 break; 1003 break;
1033 1004
1034 case on_failure_keep_string_jump: 1005 case on_failure_keep_string_jump:
1035 extract_number_and_incr (&mcnt, &p); 1006 EXTRACT_NUMBER_AND_INCR (mcnt, p);
1036 fprintf (stderr, "/on_failure_keep_string_jump to %d", p + mcnt - start); 1007 fprintf (stderr, "/on_failure_keep_string_jump to %td",
1008 p + mcnt - start);
1037 break; 1009 break;
1038 1010
1039 case on_failure_jump_nastyloop: 1011 case on_failure_jump_nastyloop:
1040 extract_number_and_incr (&mcnt, &p); 1012 EXTRACT_NUMBER_AND_INCR (mcnt, p);
1041 fprintf (stderr, "/on_failure_jump_nastyloop to %d", p + mcnt - start); 1013 fprintf (stderr, "/on_failure_jump_nastyloop to %td",
1014 p + mcnt - start);
1042 break; 1015 break;
1043 1016
1044 case on_failure_jump_loop: 1017 case on_failure_jump_loop:
1045 extract_number_and_incr (&mcnt, &p); 1018 EXTRACT_NUMBER_AND_INCR (mcnt, p);
1046 fprintf (stderr, "/on_failure_jump_loop to %d", p + mcnt - start); 1019 fprintf (stderr, "/on_failure_jump_loop to %td",
1020 p + mcnt - start);
1047 break; 1021 break;
1048 1022
1049 case on_failure_jump_smart: 1023 case on_failure_jump_smart:
1050 extract_number_and_incr (&mcnt, &p); 1024 EXTRACT_NUMBER_AND_INCR (mcnt, p);
1051 fprintf (stderr, "/on_failure_jump_smart to %d", p + mcnt - start); 1025 fprintf (stderr, "/on_failure_jump_smart to %td",
1026 p + mcnt - start);
1052 break; 1027 break;
1053 1028
1054 case jump: 1029 case jump:
1055 extract_number_and_incr (&mcnt, &p); 1030 EXTRACT_NUMBER_AND_INCR (mcnt, p);
1056 fprintf (stderr, "/jump to %d", p + mcnt - start); 1031 fprintf (stderr, "/jump to %td", p + mcnt - start);
1057 break; 1032 break;
1058 1033
1059 case succeed_n: 1034 case succeed_n:
1060 extract_number_and_incr (&mcnt, &p); 1035 EXTRACT_NUMBER_AND_INCR (mcnt, p);
1061 extract_number_and_incr (&mcnt2, &p); 1036 EXTRACT_NUMBER_AND_INCR (mcnt2, p);
1062 fprintf (stderr, "/succeed_n to %d, %d times", p - 2 + mcnt - start, mcnt2); 1037 fprintf (stderr, "/succeed_n to %td, %d times",
1038 p - 2 + mcnt - start, mcnt2);
1063 break; 1039 break;
1064 1040
1065 case jump_n: 1041 case jump_n:
1066 extract_number_and_incr (&mcnt, &p); 1042 EXTRACT_NUMBER_AND_INCR (mcnt, p);
1067 extract_number_and_incr (&mcnt2, &p); 1043 EXTRACT_NUMBER_AND_INCR (mcnt2, p);
1068 fprintf (stderr, "/jump_n to %d, %d times", p - 2 + mcnt - start, mcnt2); 1044 fprintf (stderr, "/jump_n to %td, %d times",
1045 p - 2 + mcnt - start, mcnt2);
1069 break; 1046 break;
1070 1047
1071 case set_number_at: 1048 case set_number_at:
1072 extract_number_and_incr (&mcnt, &p); 1049 EXTRACT_NUMBER_AND_INCR (mcnt, p);
1073 extract_number_and_incr (&mcnt2, &p); 1050 EXTRACT_NUMBER_AND_INCR (mcnt2, p);
1074 fprintf (stderr, "/set_number_at location %d to %d", p - 2 + mcnt - start, mcnt2); 1051 fprintf (stderr, "/set_number_at location %td to %d",
1052 p - 2 + mcnt - start, mcnt2);
1075 break; 1053 break;
1076 1054
1077 case wordbound: 1055 case wordbound:
@@ -1151,13 +1129,12 @@ print_partial_compiled_pattern (start, end)
1151 fprintf (stderr, "\n"); 1129 fprintf (stderr, "\n");
1152 } 1130 }
1153 1131
1154 fprintf (stderr, "%d:\tend of pattern.\n", p - start); 1132 fprintf (stderr, "%td:\tend of pattern.\n", p - start);
1155} 1133}
1156 1134
1157 1135
1158void 1136static void
1159print_compiled_pattern (bufp) 1137print_compiled_pattern (struct re_pattern_buffer *bufp)
1160 struct re_pattern_buffer *bufp;
1161{ 1138{
1162 re_char *buffer = bufp->buffer; 1139 re_char *buffer = bufp->buffer;
1163 1140
@@ -1171,7 +1148,7 @@ print_compiled_pattern (bufp)
1171 print_fastmap (bufp->fastmap); 1148 print_fastmap (bufp->fastmap);
1172 } 1149 }
1173 1150
1174 printf ("re_nsub: %d\t", bufp->re_nsub); 1151 printf ("re_nsub: %zu\t", bufp->re_nsub);
1175 printf ("regs_alloc: %d\t", bufp->regs_allocated); 1152 printf ("regs_alloc: %d\t", bufp->regs_allocated);
1176 printf ("can_be_null: %d\t", bufp->can_be_null); 1153 printf ("can_be_null: %d\t", bufp->can_be_null);
1177 printf ("no_sub: %d\t", bufp->no_sub); 1154 printf ("no_sub: %d\t", bufp->no_sub);
@@ -1183,13 +1160,9 @@ print_compiled_pattern (bufp)
1183} 1160}
1184 1161
1185 1162
1186void 1163static void
1187print_double_string (where, string1, size1, string2, size2) 1164print_double_string (re_char *where, re_char *string1, ssize_t size1,
1188 re_char *where; 1165 re_char *string2, ssize_t size2)
1189 re_char *string1;
1190 re_char *string2;
1191 ssize_t size1;
1192 ssize_t size2;
1193{ 1166{
1194 ssize_t this_char; 1167 ssize_t this_char;
1195 1168
@@ -1216,10 +1189,12 @@ print_double_string (where, string1, size1, string2, size2)
1216# define assert(e) 1189# define assert(e)
1217 1190
1218# define DEBUG_STATEMENT(e) 1191# define DEBUG_STATEMENT(e)
1219# define DEBUG_PRINT1(x) 1192# if __STDC_VERSION__ < 199901L
1220# define DEBUG_PRINT2(x1, x2) 1193# define DEBUG_COMPILES_ARGUMENTS
1221# define DEBUG_PRINT3(x1, x2, x3) 1194# define DEBUG_PRINT /* 'DEBUG_PRINT (x, y)' discards X and Y. */ (void)
1222# define DEBUG_PRINT4(x1, x2, x3, x4) 1195# else
1196# define DEBUG_PRINT(...)
1197# endif
1223# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) 1198# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
1224# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) 1199# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
1225 1200
@@ -1469,20 +1444,21 @@ typedef struct
1469while (REMAINING_AVAIL_SLOTS <= space) { \ 1444while (REMAINING_AVAIL_SLOTS <= space) { \
1470 if (!GROW_FAIL_STACK (fail_stack)) \ 1445 if (!GROW_FAIL_STACK (fail_stack)) \
1471 return -2; \ 1446 return -2; \
1472 DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", (fail_stack).size);\ 1447 DEBUG_PRINT ("\n Doubled stack; size now: %zd\n", (fail_stack).size);\
1473 DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ 1448 DEBUG_PRINT (" slots available: %zd\n", REMAINING_AVAIL_SLOTS);\
1474} 1449}
1475 1450
1476/* Push register NUM onto the stack. */ 1451/* Push register NUM onto the stack. */
1477#define PUSH_FAILURE_REG(num) \ 1452#define PUSH_FAILURE_REG(num) \
1478do { \ 1453do { \
1479 char *destination; \ 1454 char *destination; \
1455 long n = num; \
1480 ENSURE_FAIL_STACK(3); \ 1456 ENSURE_FAIL_STACK(3); \
1481 DEBUG_PRINT4 (" Push reg %d (spanning %p -> %p)\n", \ 1457 DEBUG_PRINT (" Push reg %ld (spanning %p -> %p)\n", \
1482 num, regstart[num], regend[num]); \ 1458 n, regstart[n], regend[n]); \
1483 PUSH_FAILURE_POINTER (regstart[num]); \ 1459 PUSH_FAILURE_POINTER (regstart[n]); \
1484 PUSH_FAILURE_POINTER (regend[num]); \ 1460 PUSH_FAILURE_POINTER (regend[n]); \
1485 PUSH_FAILURE_INT (num); \ 1461 PUSH_FAILURE_INT (n); \
1486} while (0) 1462} while (0)
1487 1463
1488/* Change the counter's value to VAL, but make sure that it will 1464/* Change the counter's value to VAL, but make sure that it will
@@ -1493,7 +1469,7 @@ do { \
1493 int c; \ 1469 int c; \
1494 ENSURE_FAIL_STACK(3); \ 1470 ENSURE_FAIL_STACK(3); \
1495 EXTRACT_NUMBER (c, ptr); \ 1471 EXTRACT_NUMBER (c, ptr); \
1496 DEBUG_PRINT4 (" Push number %p = %d -> %d\n", ptr, c, val); \ 1472 DEBUG_PRINT (" Push number %p = %d -> %d\n", ptr, c, val); \
1497 PUSH_FAILURE_INT (c); \ 1473 PUSH_FAILURE_INT (c); \
1498 PUSH_FAILURE_POINTER (ptr); \ 1474 PUSH_FAILURE_POINTER (ptr); \
1499 PUSH_FAILURE_INT (-1); \ 1475 PUSH_FAILURE_INT (-1); \
@@ -1511,14 +1487,14 @@ do { \
1511 unsigned char *ptr = (unsigned char*) POP_FAILURE_POINTER (); \ 1487 unsigned char *ptr = (unsigned char*) POP_FAILURE_POINTER (); \
1512 pfreg = POP_FAILURE_INT (); \ 1488 pfreg = POP_FAILURE_INT (); \
1513 STORE_NUMBER (ptr, pfreg); \ 1489 STORE_NUMBER (ptr, pfreg); \
1514 DEBUG_PRINT3 (" Pop counter %p = %d\n", ptr, pfreg); \ 1490 DEBUG_PRINT (" Pop counter %p = %ld\n", ptr, pfreg); \
1515 } \ 1491 } \
1516 else \ 1492 else \
1517 { \ 1493 { \
1518 regend[pfreg] = POP_FAILURE_POINTER (); \ 1494 regend[pfreg] = POP_FAILURE_POINTER (); \
1519 regstart[pfreg] = POP_FAILURE_POINTER (); \ 1495 regstart[pfreg] = POP_FAILURE_POINTER (); \
1520 DEBUG_PRINT4 (" Pop reg %d (spanning %p -> %p)\n", \ 1496 DEBUG_PRINT (" Pop reg %ld (spanning %p -> %p)\n", \
1521 pfreg, regstart[pfreg], regend[pfreg]); \ 1497 pfreg, regstart[pfreg], regend[pfreg]); \
1522 } \ 1498 } \
1523} while (0) 1499} while (0)
1524 1500
@@ -1538,10 +1514,10 @@ do { \
1538 cycle = 1; \ 1514 cycle = 1; \
1539 break; \ 1515 break; \
1540 } \ 1516 } \
1541 DEBUG_PRINT2 (" Other pattern: %p\n", FAILURE_PAT (failure)); \ 1517 DEBUG_PRINT (" Other pattern: %p\n", FAILURE_PAT (failure)); \
1542 failure = NEXT_FAILURE_HANDLE(failure); \ 1518 failure = NEXT_FAILURE_HANDLE(failure); \
1543 } \ 1519 } \
1544 DEBUG_PRINT2 (" Other string: %p\n", FAILURE_STR (failure)); \ 1520 DEBUG_PRINT (" Other string: %p\n", FAILURE_STR (failure)); \
1545} while (0) 1521} while (0)
1546 1522
1547/* Push the information about the state we will need 1523/* Push the information about the state we will need
@@ -1560,23 +1536,23 @@ do { \
1560 of 0 + -1 isn't done as unsigned. */ \ 1536 of 0 + -1 isn't done as unsigned. */ \
1561 \ 1537 \
1562 DEBUG_STATEMENT (nfailure_points_pushed++); \ 1538 DEBUG_STATEMENT (nfailure_points_pushed++); \
1563 DEBUG_PRINT1 ("\nPUSH_FAILURE_POINT:\n"); \ 1539 DEBUG_PRINT ("\nPUSH_FAILURE_POINT:\n"); \
1564 DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail); \ 1540 DEBUG_PRINT (" Before push, next avail: %zd\n", (fail_stack).avail); \
1565 DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ 1541 DEBUG_PRINT (" size: %zd\n", (fail_stack).size);\
1566 \ 1542 \
1567 ENSURE_FAIL_STACK (NUM_NONREG_ITEMS); \ 1543 ENSURE_FAIL_STACK (NUM_NONREG_ITEMS); \
1568 \ 1544 \
1569 DEBUG_PRINT1 ("\n"); \ 1545 DEBUG_PRINT ("\n"); \
1570 \ 1546 \
1571 DEBUG_PRINT2 (" Push frame index: %d\n", fail_stack.frame); \ 1547 DEBUG_PRINT (" Push frame index: %zd\n", fail_stack.frame); \
1572 PUSH_FAILURE_INT (fail_stack.frame); \ 1548 PUSH_FAILURE_INT (fail_stack.frame); \
1573 \ 1549 \
1574 DEBUG_PRINT2 (" Push string %p: `", string_place); \ 1550 DEBUG_PRINT (" Push string %p: `", string_place); \
1575 DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, size2);\ 1551 DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, size2);\
1576 DEBUG_PRINT1 ("'\n"); \ 1552 DEBUG_PRINT ("'\n"); \
1577 PUSH_FAILURE_POINTER (string_place); \ 1553 PUSH_FAILURE_POINTER (string_place); \
1578 \ 1554 \
1579 DEBUG_PRINT2 (" Push pattern %p: ", pattern); \ 1555 DEBUG_PRINT (" Push pattern %p: ", pattern); \
1580 DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern, pend); \ 1556 DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern, pend); \
1581 PUSH_FAILURE_POINTER (pattern); \ 1557 PUSH_FAILURE_POINTER (pattern); \
1582 \ 1558 \
@@ -1609,28 +1585,28 @@ do { \
1609 assert (!FAIL_STACK_EMPTY ()); \ 1585 assert (!FAIL_STACK_EMPTY ()); \
1610 \ 1586 \
1611 /* Remove failure points and point to how many regs pushed. */ \ 1587 /* Remove failure points and point to how many regs pushed. */ \
1612 DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ 1588 DEBUG_PRINT ("POP_FAILURE_POINT:\n"); \
1613 DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ 1589 DEBUG_PRINT (" Before pop, next avail: %zd\n", fail_stack.avail); \
1614 DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ 1590 DEBUG_PRINT (" size: %zd\n", fail_stack.size); \
1615 \ 1591 \
1616 /* Pop the saved registers. */ \ 1592 /* Pop the saved registers. */ \
1617 while (fail_stack.frame < fail_stack.avail) \ 1593 while (fail_stack.frame < fail_stack.avail) \
1618 POP_FAILURE_REG_OR_COUNT (); \ 1594 POP_FAILURE_REG_OR_COUNT (); \
1619 \ 1595 \
1620 pat = POP_FAILURE_POINTER (); \ 1596 pat = POP_FAILURE_POINTER (); \
1621 DEBUG_PRINT2 (" Popping pattern %p: ", pat); \ 1597 DEBUG_PRINT (" Popping pattern %p: ", pat); \
1622 DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ 1598 DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \
1623 \ 1599 \
1624 /* If the saved string location is NULL, it came from an \ 1600 /* If the saved string location is NULL, it came from an \
1625 on_failure_keep_string_jump opcode, and we want to throw away the \ 1601 on_failure_keep_string_jump opcode, and we want to throw away the \
1626 saved NULL, thus retaining our current position in the string. */ \ 1602 saved NULL, thus retaining our current position in the string. */ \
1627 str = POP_FAILURE_POINTER (); \ 1603 str = POP_FAILURE_POINTER (); \
1628 DEBUG_PRINT2 (" Popping string %p: `", str); \ 1604 DEBUG_PRINT (" Popping string %p: `", str); \
1629 DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ 1605 DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \
1630 DEBUG_PRINT1 ("'\n"); \ 1606 DEBUG_PRINT ("'\n"); \
1631 \ 1607 \
1632 fail_stack.frame = POP_FAILURE_INT (); \ 1608 fail_stack.frame = POP_FAILURE_INT (); \
1633 DEBUG_PRINT2 (" Popping frame index: %d\n", fail_stack.frame); \ 1609 DEBUG_PRINT (" Popping frame index: %zd\n", fail_stack.frame); \
1634 \ 1610 \
1635 assert (fail_stack.avail >= 0); \ 1611 assert (fail_stack.avail >= 0); \
1636 assert (fail_stack.frame <= fail_stack.avail); \ 1612 assert (fail_stack.frame <= fail_stack.avail); \
@@ -2493,7 +2469,7 @@ regex_compile (const re_char *pattern, size_t size, reg_syntax_t syntax, struct
2493 2469
2494#ifdef DEBUG 2470#ifdef DEBUG
2495 debug++; 2471 debug++;
2496 DEBUG_PRINT1 ("\nCompiling pattern: "); 2472 DEBUG_PRINT ("\nCompiling pattern: ");
2497 if (debug > 0) 2473 if (debug > 0)
2498 { 2474 {
2499 unsigned debug_count; 2475 unsigned debug_count;
@@ -2646,7 +2622,7 @@ regex_compile (const re_char *pattern, size_t size, reg_syntax_t syntax, struct
2646 goto normal_char; 2622 goto normal_char;
2647 handle_plus: 2623 handle_plus:
2648 case '*': 2624 case '*':
2649 /* If there is no previous pattern... */ 2625 /* If there is no previous pattern... */
2650 if (!laststart) 2626 if (!laststart)
2651 { 2627 {
2652 if (syntax & RE_CONTEXT_INVALID_OPS) 2628 if (syntax & RE_CONTEXT_INVALID_OPS)
@@ -2754,7 +2730,7 @@ regex_compile (const re_char *pattern, size_t size, reg_syntax_t syntax, struct
2754 } 2730 }
2755 } 2731 }
2756 else /* not greedy */ 2732 else /* not greedy */
2757 { /* I wish the greedy and non-greedy cases could be merged. */ 2733 { /* I wish the greedy and non-greedy cases could be merged. */
2758 2734
2759 GET_BUFFER_SPACE (7); /* We might use less. */ 2735 GET_BUFFER_SPACE (7); /* We might use less. */
2760 if (many_times_ok) 2736 if (many_times_ok)
@@ -3058,7 +3034,7 @@ regex_compile (const re_char *pattern, size_t size, reg_syntax_t syntax, struct
3058 3034
3059 /* Allocate space for COUNT + RANGE_TABLE. Needs two 3035 /* Allocate space for COUNT + RANGE_TABLE. Needs two
3060 bytes for flags, two for COUNT, and three bytes for 3036 bytes for flags, two for COUNT, and three bytes for
3061 each character. */ 3037 each character. */
3062 GET_BUFFER_SPACE (4 + used * 3); 3038 GET_BUFFER_SPACE (4 + used * 3);
3063 3039
3064 /* Indicate the existence of range table. */ 3040 /* Indicate the existence of range table. */
@@ -3485,6 +3461,7 @@ regex_compile (const re_char *pattern, size_t size, reg_syntax_t syntax, struct
3485 /* There is no way to specify the before_dot and after_dot 3461 /* There is no way to specify the before_dot and after_dot
3486 operators. rms says this is ok. --karl */ 3462 operators. rms says this is ok. --karl */
3487 case '=': 3463 case '=':
3464 laststart = b;
3488 BUF_PUSH (at_dot); 3465 BUF_PUSH (at_dot);
3489 break; 3466 break;
3490 3467
@@ -3533,12 +3510,14 @@ regex_compile (const re_char *pattern, size_t size, reg_syntax_t syntax, struct
3533 case '<': 3510 case '<':
3534 if (syntax & RE_NO_GNU_OPS) 3511 if (syntax & RE_NO_GNU_OPS)
3535 goto normal_char; 3512 goto normal_char;
3513 laststart = b;
3536 BUF_PUSH (wordbeg); 3514 BUF_PUSH (wordbeg);
3537 break; 3515 break;
3538 3516
3539 case '>': 3517 case '>':
3540 if (syntax & RE_NO_GNU_OPS) 3518 if (syntax & RE_NO_GNU_OPS)
3541 goto normal_char; 3519 goto normal_char;
3520 laststart = b;
3542 BUF_PUSH (wordend); 3521 BUF_PUSH (wordend);
3543 break; 3522 break;
3544 3523
@@ -3697,7 +3676,7 @@ regex_compile (const re_char *pattern, size_t size, reg_syntax_t syntax, struct
3697 if (debug > 0) 3676 if (debug > 0)
3698 { 3677 {
3699 re_compile_fastmap (bufp); 3678 re_compile_fastmap (bufp);
3700 DEBUG_PRINT1 ("\nCompiled pattern: \n"); 3679 DEBUG_PRINT ("\nCompiled pattern: \n");
3701 print_compiled_pattern (bufp); 3680 print_compiled_pattern (bufp);
3702 } 3681 }
3703 debug--; 3682 debug--;
@@ -4523,8 +4502,8 @@ static int bcmp_translate (re_char *s1, re_char *s2,
4523 and `string2' into an offset from the beginning of that string. */ 4502 and `string2' into an offset from the beginning of that string. */
4524#define POINTER_TO_OFFSET(ptr) \ 4503#define POINTER_TO_OFFSET(ptr) \
4525 (FIRST_STRING_P (ptr) \ 4504 (FIRST_STRING_P (ptr) \
4526 ? ((regoff_t) ((ptr) - string1)) \ 4505 ? (ptr) - string1 \
4527 : ((regoff_t) ((ptr) - string2 + size1))) 4506 : (ptr) - string2 + (ptrdiff_t) size1)
4528 4507
4529/* Call before fetching a character with *d. This switches over to 4508/* Call before fetching a character with *d. This switches over to
4530 string2 if necessary. 4509 string2 if necessary.
@@ -4711,7 +4690,7 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, const re_char *p1, const r
4711 /* If we're at the end of the pattern, we can change. */ 4690 /* If we're at the end of the pattern, we can change. */
4712 if (skip_one_char (p1)) 4691 if (skip_one_char (p1))
4713 { 4692 {
4714 DEBUG_PRINT1 (" End of pattern: fast loop.\n"); 4693 DEBUG_PRINT (" End of pattern: fast loop.\n");
4715 return 1; 4694 return 1;
4716 } 4695 }
4717 break; 4696 break;
@@ -4727,7 +4706,7 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, const re_char *p1, const r
4727 { 4706 {
4728 if (c != RE_STRING_CHAR (p1 + 2, multibyte)) 4707 if (c != RE_STRING_CHAR (p1 + 2, multibyte))
4729 { 4708 {
4730 DEBUG_PRINT3 (" '%c' != '%c' => fast loop.\n", c, p1[2]); 4709 DEBUG_PRINT (" '%c' != '%c' => fast loop.\n", c, p1[2]);
4731 return 1; 4710 return 1;
4732 } 4711 }
4733 } 4712 }
@@ -4752,14 +4731,14 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, const re_char *p1, const r
4752 that we can't change to pop_failure_jump. */ 4731 that we can't change to pop_failure_jump. */
4753 if (!not) 4732 if (!not)
4754 { 4733 {
4755 DEBUG_PRINT1 (" No match => fast loop.\n"); 4734 DEBUG_PRINT (" No match => fast loop.\n");
4756 return 1; 4735 return 1;
4757 } 4736 }
4758 } 4737 }
4759 else if ((re_opcode_t) *p1 == anychar 4738 else if ((re_opcode_t) *p1 == anychar
4760 && c == '\n') 4739 && c == '\n')
4761 { 4740 {
4762 DEBUG_PRINT1 (" . != \\n => fast loop.\n"); 4741 DEBUG_PRINT (" . != \\n => fast loop.\n");
4763 return 1; 4742 return 1;
4764 } 4743 }
4765 } 4744 }
@@ -4802,7 +4781,7 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, const re_char *p1, const r
4802 if (idx == p2[1] 4781 if (idx == p2[1]
4803 || idx == CHARSET_BITMAP_SIZE (p1)) 4782 || idx == CHARSET_BITMAP_SIZE (p1))
4804 { 4783 {
4805 DEBUG_PRINT1 (" No match => fast loop.\n"); 4784 DEBUG_PRINT (" No match => fast loop.\n");
4806 return 1; 4785 return 1;
4807 } 4786 }
4808 } 4787 }
@@ -4819,7 +4798,7 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, const re_char *p1, const r
4819 4798
4820 if (idx == p2[1]) 4799 if (idx == p2[1])
4821 { 4800 {
4822 DEBUG_PRINT1 (" No match => fast loop.\n"); 4801 DEBUG_PRINT (" No match => fast loop.\n");
4823 return 1; 4802 return 1;
4824 } 4803 }
4825 } 4804 }
@@ -4945,7 +4924,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
4945 ssize_t pos, struct re_registers *regs, ssize_t stop) 4924 ssize_t pos, struct re_registers *regs, ssize_t stop)
4946{ 4925{
4947 /* General temporaries. */ 4926 /* General temporaries. */
4948 ssize_t mcnt; 4927 int mcnt;
4949 size_t reg; 4928 size_t reg;
4950 4929
4951 /* Just past the end of the corresponding string. */ 4930 /* Just past the end of the corresponding string. */
@@ -4987,7 +4966,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
4987#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ 4966#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */
4988 fail_stack_type fail_stack; 4967 fail_stack_type fail_stack;
4989#endif 4968#endif
4990#ifdef DEBUG 4969#ifdef DEBUG_COMPILES_ARGUMENTS
4991 unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; 4970 unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
4992#endif 4971#endif
4993 4972
@@ -5032,12 +5011,12 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5032 and need to test it, it's not garbage. */ 5011 and need to test it, it's not garbage. */
5033 re_char *match_end = NULL; 5012 re_char *match_end = NULL;
5034 5013
5035#ifdef DEBUG 5014#ifdef DEBUG_COMPILES_ARGUMENTS
5036 /* Counts the total number of registers pushed. */ 5015 /* Counts the total number of registers pushed. */
5037 unsigned num_regs_pushed = 0; 5016 unsigned num_regs_pushed = 0;
5038#endif 5017#endif
5039 5018
5040 DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); 5019 DEBUG_PRINT ("\n\nEntering re_match_2.\n");
5041 5020
5042 INIT_FAIL_STACK (); 5021 INIT_FAIL_STACK ();
5043 5022
@@ -5133,22 +5112,25 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5133 dend = end_match_1; 5112 dend = end_match_1;
5134 } 5113 }
5135 5114
5136 DEBUG_PRINT1 ("The compiled pattern is: "); 5115 DEBUG_PRINT ("The compiled pattern is: ");
5137 DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); 5116 DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
5138 DEBUG_PRINT1 ("The string to match is: `"); 5117 DEBUG_PRINT ("The string to match is: `");
5139 DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); 5118 DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
5140 DEBUG_PRINT1 ("'\n"); 5119 DEBUG_PRINT ("'\n");
5141 5120
5142 /* This loops over pattern commands. It exits by returning from the 5121 /* This loops over pattern commands. It exits by returning from the
5143 function if the match is complete, or it drops through if the match 5122 function if the match is complete, or it drops through if the match
5144 fails at this starting point in the input data. */ 5123 fails at this starting point in the input data. */
5145 for (;;) 5124 for (;;)
5146 { 5125 {
5147 DEBUG_PRINT2 ("\n%p: ", p); 5126 DEBUG_PRINT ("\n%p: ", p);
5148 5127
5149 if (p == pend) 5128 if (p == pend)
5150 { /* End of pattern means we might have succeeded. */ 5129 {
5151 DEBUG_PRINT1 ("end of pattern ... "); 5130 ptrdiff_t dcnt;
5131
5132 /* End of pattern means we might have succeeded. */
5133 DEBUG_PRINT ("end of pattern ... ");
5152 5134
5153 /* If we haven't matched the entire string, and we want the 5135 /* If we haven't matched the entire string, and we want the
5154 longest match, try backtracking. */ 5136 longest match, try backtracking. */
@@ -5168,7 +5150,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5168 else 5150 else
5169 best_match_p = !FIRST_STRING_P (d); 5151 best_match_p = !FIRST_STRING_P (d);
5170 5152
5171 DEBUG_PRINT1 ("backtracking.\n"); 5153 DEBUG_PRINT ("backtracking.\n");
5172 5154
5173 if (!FAIL_STACK_EMPTY ()) 5155 if (!FAIL_STACK_EMPTY ())
5174 { /* More failure points to try. */ 5156 { /* More failure points to try. */
@@ -5179,7 +5161,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5179 best_regs_set = true; 5161 best_regs_set = true;
5180 match_end = d; 5162 match_end = d;
5181 5163
5182 DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); 5164 DEBUG_PRINT ("\nSAVING match as best so far.\n");
5183 5165
5184 for (reg = 1; reg < num_regs; reg++) 5166 for (reg = 1; reg < num_regs; reg++)
5185 { 5167 {
@@ -5201,7 +5183,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5201 For example, the pattern `x.*y.*z' against the 5183 For example, the pattern `x.*y.*z' against the
5202 strings `x-' and `y-z-', if the two strings are 5184 strings `x-' and `y-z-', if the two strings are
5203 not consecutive in memory. */ 5185 not consecutive in memory. */
5204 DEBUG_PRINT1 ("Restoring best registers.\n"); 5186 DEBUG_PRINT ("Restoring best registers.\n");
5205 5187
5206 d = match_end; 5188 d = match_end;
5207 dend = ((d >= string1 && d <= end1) 5189 dend = ((d >= string1 && d <= end1)
@@ -5216,7 +5198,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5216 } /* d != end_match_2 */ 5198 } /* d != end_match_2 */
5217 5199
5218 succeed_label: 5200 succeed_label:
5219 DEBUG_PRINT1 ("Accepting match.\n"); 5201 DEBUG_PRINT ("Accepting match.\n");
5220 5202
5221 /* If caller wants register contents data back, do it. */ 5203 /* If caller wants register contents data back, do it. */
5222 if (regs && !bufp->no_sub) 5204 if (regs && !bufp->no_sub)
@@ -5276,10 +5258,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5276 regs->start[reg] = regs->end[reg] = -1; 5258 regs->start[reg] = regs->end[reg] = -1;
5277 else 5259 else
5278 { 5260 {
5279 regs->start[reg] 5261 regs->start[reg] = POINTER_TO_OFFSET (regstart[reg]);
5280 = (regoff_t) POINTER_TO_OFFSET (regstart[reg]); 5262 regs->end[reg] = POINTER_TO_OFFSET (regend[reg]);
5281 regs->end[reg]
5282 = (regoff_t) POINTER_TO_OFFSET (regend[reg]);
5283 } 5263 }
5284 } 5264 }
5285 5265
@@ -5292,17 +5272,17 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5292 regs->start[reg] = regs->end[reg] = -1; 5272 regs->start[reg] = regs->end[reg] = -1;
5293 } /* regs && !bufp->no_sub */ 5273 } /* regs && !bufp->no_sub */
5294 5274
5295 DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", 5275 DEBUG_PRINT ("%u failure points pushed, %u popped (%u remain).\n",
5296 nfailure_points_pushed, nfailure_points_popped, 5276 nfailure_points_pushed, nfailure_points_popped,
5297 nfailure_points_pushed - nfailure_points_popped); 5277 nfailure_points_pushed - nfailure_points_popped);
5298 DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); 5278 DEBUG_PRINT ("%u registers pushed.\n", num_regs_pushed);
5299 5279
5300 mcnt = POINTER_TO_OFFSET (d) - pos; 5280 dcnt = POINTER_TO_OFFSET (d) - pos;
5301 5281
5302 DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); 5282 DEBUG_PRINT ("Returning %td from re_match_2.\n", dcnt);
5303 5283
5304 FREE_VARIABLES (); 5284 FREE_VARIABLES ();
5305 return mcnt; 5285 return dcnt;
5306 } 5286 }
5307 5287
5308 /* Otherwise match next pattern command. */ 5288 /* Otherwise match next pattern command. */
@@ -5311,11 +5291,11 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5311 /* Ignore these. Used to ignore the n of succeed_n's which 5291 /* Ignore these. Used to ignore the n of succeed_n's which
5312 currently have n == 0. */ 5292 currently have n == 0. */
5313 case no_op: 5293 case no_op:
5314 DEBUG_PRINT1 ("EXECUTING no_op.\n"); 5294 DEBUG_PRINT ("EXECUTING no_op.\n");
5315 break; 5295 break;
5316 5296
5317 case succeed: 5297 case succeed:
5318 DEBUG_PRINT1 ("EXECUTING succeed.\n"); 5298 DEBUG_PRINT ("EXECUTING succeed.\n");
5319 goto succeed_label; 5299 goto succeed_label;
5320 5300
5321 /* Match the next n pattern characters exactly. The following 5301 /* Match the next n pattern characters exactly. The following
@@ -5323,7 +5303,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5323 are the characters to match. */ 5303 are the characters to match. */
5324 case exactn: 5304 case exactn:
5325 mcnt = *p++; 5305 mcnt = *p++;
5326 DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); 5306 DEBUG_PRINT ("EXECUTING exactn %d.\n", mcnt);
5327 5307
5328 /* Remember the start point to rollback upon failure. */ 5308 /* Remember the start point to rollback upon failure. */
5329 dfail = d; 5309 dfail = d;
@@ -5429,7 +5409,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5429 int buf_charlen; 5409 int buf_charlen;
5430 re_wchar_t buf_ch; 5410 re_wchar_t buf_ch;
5431 5411
5432 DEBUG_PRINT1 ("EXECUTING anychar.\n"); 5412 DEBUG_PRINT ("EXECUTING anychar.\n");
5433 5413
5434 PREFETCH (); 5414 PREFETCH ();
5435 buf_ch = RE_STRING_CHAR_AND_LENGTH (d, buf_charlen, 5415 buf_ch = RE_STRING_CHAR_AND_LENGTH (d, buf_charlen,
@@ -5442,7 +5422,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5442 && buf_ch == '\000')) 5422 && buf_ch == '\000'))
5443 goto fail; 5423 goto fail;
5444 5424
5445 DEBUG_PRINT2 (" Matched `%d'.\n", *d); 5425 DEBUG_PRINT (" Matched `%d'.\n", *d);
5446 d += buf_charlen; 5426 d += buf_charlen;
5447 } 5427 }
5448 break; 5428 break;
@@ -5469,7 +5449,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5469 /* Whether matching against a unibyte character. */ 5449 /* Whether matching against a unibyte character. */
5470 boolean unibyte_char = false; 5450 boolean unibyte_char = false;
5471 5451
5472 DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); 5452 DEBUG_PRINT ("EXECUTING charset%s.\n", not ? "_not" : "");
5473 5453
5474 range_table_exists = CHARSET_RANGE_TABLE_EXISTS_P (&p[-1]); 5454 range_table_exists = CHARSET_RANGE_TABLE_EXISTS_P (&p[-1]);
5475 5455
@@ -5553,14 +5533,14 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5553 matched within the group is recorded (in the internal 5533 matched within the group is recorded (in the internal
5554 registers data structure) under the register number. */ 5534 registers data structure) under the register number. */
5555 case start_memory: 5535 case start_memory:
5556 DEBUG_PRINT2 ("EXECUTING start_memory %d:\n", *p); 5536 DEBUG_PRINT ("EXECUTING start_memory %d:\n", *p);
5557 5537
5558 /* In case we need to undo this operation (via backtracking). */ 5538 /* In case we need to undo this operation (via backtracking). */
5559 PUSH_FAILURE_REG ((unsigned int)*p); 5539 PUSH_FAILURE_REG (*p);
5560 5540
5561 regstart[*p] = d; 5541 regstart[*p] = d;
5562 regend[*p] = NULL; /* probably unnecessary. -sm */ 5542 regend[*p] = NULL; /* probably unnecessary. -sm */
5563 DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); 5543 DEBUG_PRINT (" regstart: %td\n", POINTER_TO_OFFSET (regstart[*p]));
5564 5544
5565 /* Move past the register number and inner group count. */ 5545 /* Move past the register number and inner group count. */
5566 p += 1; 5546 p += 1;
@@ -5570,7 +5550,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5570 /* The stop_memory opcode represents the end of a group. Its 5550 /* The stop_memory opcode represents the end of a group. Its
5571 argument is the same as start_memory's: the register number. */ 5551 argument is the same as start_memory's: the register number. */
5572 case stop_memory: 5552 case stop_memory:
5573 DEBUG_PRINT2 ("EXECUTING stop_memory %d:\n", *p); 5553 DEBUG_PRINT ("EXECUTING stop_memory %d:\n", *p);
5574 5554
5575 assert (!REG_UNSET (regstart[*p])); 5555 assert (!REG_UNSET (regstart[*p]));
5576 /* Strictly speaking, there should be code such as: 5556 /* Strictly speaking, there should be code such as:
@@ -5588,7 +5568,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5588 is *not* undone. */ 5568 is *not* undone. */
5589 5569
5590 regend[*p] = d; 5570 regend[*p] = d;
5591 DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); 5571 DEBUG_PRINT (" regend: %td\n", POINTER_TO_OFFSET (regend[*p]));
5592 5572
5593 /* Move past the register number and the inner group count. */ 5573 /* Move past the register number and the inner group count. */
5594 p += 1; 5574 p += 1;
@@ -5601,7 +5581,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5601 { 5581 {
5602 register re_char *d2, *dend2; 5582 register re_char *d2, *dend2;
5603 int regno = *p++; /* Get which register to match against. */ 5583 int regno = *p++; /* Get which register to match against. */
5604 DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); 5584 DEBUG_PRINT ("EXECUTING duplicate %d.\n", regno);
5605 5585
5606 /* Can't back reference a group which we've never matched. */ 5586 /* Can't back reference a group which we've never matched. */
5607 if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) 5587 if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
@@ -5623,6 +5603,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5623 ? regend[regno] : end_match_1); 5603 ? regend[regno] : end_match_1);
5624 for (;;) 5604 for (;;)
5625 { 5605 {
5606 ptrdiff_t dcnt;
5607
5626 /* If necessary, advance to next segment in register 5608 /* If necessary, advance to next segment in register
5627 contents. */ 5609 contents. */
5628 while (d2 == dend2) 5610 while (d2 == dend2)
@@ -5641,23 +5623,23 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5641 PREFETCH (); 5623 PREFETCH ();
5642 5624
5643 /* How many characters left in this segment to match. */ 5625 /* How many characters left in this segment to match. */
5644 mcnt = dend - d; 5626 dcnt = dend - d;
5645 5627
5646 /* Want how many consecutive characters we can match in 5628 /* Want how many consecutive characters we can match in
5647 one shot, so, if necessary, adjust the count. */ 5629 one shot, so, if necessary, adjust the count. */
5648 if (mcnt > dend2 - d2) 5630 if (dcnt > dend2 - d2)
5649 mcnt = dend2 - d2; 5631 dcnt = dend2 - d2;
5650 5632
5651 /* Compare that many; failure if mismatch, else move 5633 /* Compare that many; failure if mismatch, else move
5652 past them. */ 5634 past them. */
5653 if (RE_TRANSLATE_P (translate) 5635 if (RE_TRANSLATE_P (translate)
5654 ? bcmp_translate (d, d2, mcnt, translate, target_multibyte) 5636 ? bcmp_translate (d, d2, dcnt, translate, target_multibyte)
5655 : memcmp (d, d2, mcnt)) 5637 : memcmp (d, d2, dcnt))
5656 { 5638 {
5657 d = dfail; 5639 d = dfail;
5658 goto fail; 5640 goto fail;
5659 } 5641 }
5660 d += mcnt, d2 += mcnt; 5642 d += dcnt, d2 += dcnt;
5661 } 5643 }
5662 } 5644 }
5663 break; 5645 break;
@@ -5666,7 +5648,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5666 /* begline matches the empty string at the beginning of the string 5648 /* begline matches the empty string at the beginning of the string
5667 (unless `not_bol' is set in `bufp'), and after newlines. */ 5649 (unless `not_bol' is set in `bufp'), and after newlines. */
5668 case begline: 5650 case begline:
5669 DEBUG_PRINT1 ("EXECUTING begline.\n"); 5651 DEBUG_PRINT ("EXECUTING begline.\n");
5670 5652
5671 if (AT_STRINGS_BEG (d)) 5653 if (AT_STRINGS_BEG (d))
5672 { 5654 {
@@ -5685,7 +5667,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5685 5667
5686 /* endline is the dual of begline. */ 5668 /* endline is the dual of begline. */
5687 case endline: 5669 case endline:
5688 DEBUG_PRINT1 ("EXECUTING endline.\n"); 5670 DEBUG_PRINT ("EXECUTING endline.\n");
5689 5671
5690 if (AT_STRINGS_END (d)) 5672 if (AT_STRINGS_END (d))
5691 { 5673 {
@@ -5702,7 +5684,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5702 5684
5703 /* Match at the very beginning of the data. */ 5685 /* Match at the very beginning of the data. */
5704 case begbuf: 5686 case begbuf:
5705 DEBUG_PRINT1 ("EXECUTING begbuf.\n"); 5687 DEBUG_PRINT ("EXECUTING begbuf.\n");
5706 if (AT_STRINGS_BEG (d)) 5688 if (AT_STRINGS_BEG (d))
5707 break; 5689 break;
5708 goto fail; 5690 goto fail;
@@ -5710,7 +5692,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5710 5692
5711 /* Match at the very end of the data. */ 5693 /* Match at the very end of the data. */
5712 case endbuf: 5694 case endbuf:
5713 DEBUG_PRINT1 ("EXECUTING endbuf.\n"); 5695 DEBUG_PRINT ("EXECUTING endbuf.\n");
5714 if (AT_STRINGS_END (d)) 5696 if (AT_STRINGS_END (d))
5715 break; 5697 break;
5716 goto fail; 5698 goto fail;
@@ -5734,8 +5716,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5734 case; that seems worse than this. */ 5716 case; that seems worse than this. */
5735 case on_failure_keep_string_jump: 5717 case on_failure_keep_string_jump:
5736 EXTRACT_NUMBER_AND_INCR (mcnt, p); 5718 EXTRACT_NUMBER_AND_INCR (mcnt, p);
5737 DEBUG_PRINT3 ("EXECUTING on_failure_keep_string_jump %d (to %p):\n", 5719 DEBUG_PRINT ("EXECUTING on_failure_keep_string_jump %d (to %p):\n",
5738 mcnt, p + mcnt); 5720 mcnt, p + mcnt);
5739 5721
5740 PUSH_FAILURE_POINT (p - 3, NULL); 5722 PUSH_FAILURE_POINT (p - 3, NULL);
5741 break; 5723 break;
@@ -5756,8 +5738,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5756 the loop. */ 5738 the loop. */
5757 case on_failure_jump_nastyloop: 5739 case on_failure_jump_nastyloop:
5758 EXTRACT_NUMBER_AND_INCR (mcnt, p); 5740 EXTRACT_NUMBER_AND_INCR (mcnt, p);
5759 DEBUG_PRINT3 ("EXECUTING on_failure_jump_nastyloop %d (to %p):\n", 5741 DEBUG_PRINT ("EXECUTING on_failure_jump_nastyloop %d (to %p):\n",
5760 mcnt, p + mcnt); 5742 mcnt, p + mcnt);
5761 5743
5762 assert ((re_opcode_t)p[-4] == no_op); 5744 assert ((re_opcode_t)p[-4] == no_op);
5763 { 5745 {
@@ -5777,8 +5759,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5777 case on_failure_jump_loop: 5759 case on_failure_jump_loop:
5778 on_failure: 5760 on_failure:
5779 EXTRACT_NUMBER_AND_INCR (mcnt, p); 5761 EXTRACT_NUMBER_AND_INCR (mcnt, p);
5780 DEBUG_PRINT3 ("EXECUTING on_failure_jump_loop %d (to %p):\n", 5762 DEBUG_PRINT ("EXECUTING on_failure_jump_loop %d (to %p):\n",
5781 mcnt, p + mcnt); 5763 mcnt, p + mcnt);
5782 { 5764 {
5783 int cycle = 0; 5765 int cycle = 0;
5784 CHECK_INFINITE_LOOP (p - 3, d); 5766 CHECK_INFINITE_LOOP (p - 3, d);
@@ -5809,8 +5791,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5809 pop_failure_jump back to this on_failure_jump. */ 5791 pop_failure_jump back to this on_failure_jump. */
5810 case on_failure_jump: 5792 case on_failure_jump:
5811 EXTRACT_NUMBER_AND_INCR (mcnt, p); 5793 EXTRACT_NUMBER_AND_INCR (mcnt, p);
5812 DEBUG_PRINT3 ("EXECUTING on_failure_jump %d (to %p):\n", 5794 DEBUG_PRINT ("EXECUTING on_failure_jump %d (to %p):\n",
5813 mcnt, p + mcnt); 5795 mcnt, p + mcnt);
5814 5796
5815 PUSH_FAILURE_POINT (p -3, d); 5797 PUSH_FAILURE_POINT (p -3, d);
5816 break; 5798 break;
@@ -5824,8 +5806,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5824 on_failure_keep_string_jump instead of on_failure_jump. */ 5806 on_failure_keep_string_jump instead of on_failure_jump. */
5825 case on_failure_jump_smart: 5807 case on_failure_jump_smart:
5826 EXTRACT_NUMBER_AND_INCR (mcnt, p); 5808 EXTRACT_NUMBER_AND_INCR (mcnt, p);
5827 DEBUG_PRINT3 ("EXECUTING on_failure_jump_smart %d (to %p).\n", 5809 DEBUG_PRINT ("EXECUTING on_failure_jump_smart %d (to %p).\n",
5828 mcnt, p + mcnt); 5810 mcnt, p + mcnt);
5829 { 5811 {
5830 re_char *p1 = p; /* Next operation. */ 5812 re_char *p1 = p; /* Next operation. */
5831 /* Here, we discard `const', making re_match non-reentrant. */ 5813 /* Here, we discard `const', making re_match non-reentrant. */
@@ -5845,14 +5827,14 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5845 if (mutually_exclusive_p (bufp, p1, p2)) 5827 if (mutually_exclusive_p (bufp, p1, p2))
5846 { 5828 {
5847 /* Use a fast `on_failure_keep_string_jump' loop. */ 5829 /* Use a fast `on_failure_keep_string_jump' loop. */
5848 DEBUG_PRINT1 (" smart exclusive => fast loop.\n"); 5830 DEBUG_PRINT (" smart exclusive => fast loop.\n");
5849 *p3 = (unsigned char) on_failure_keep_string_jump; 5831 *p3 = (unsigned char) on_failure_keep_string_jump;
5850 STORE_NUMBER (p2 - 2, mcnt + 3); 5832 STORE_NUMBER (p2 - 2, mcnt + 3);
5851 } 5833 }
5852 else 5834 else
5853 { 5835 {
5854 /* Default to a safe `on_failure_jump' loop. */ 5836 /* Default to a safe `on_failure_jump' loop. */
5855 DEBUG_PRINT1 (" smart default => slow loop.\n"); 5837 DEBUG_PRINT (" smart default => slow loop.\n");
5856 *p3 = (unsigned char) on_failure_jump; 5838 *p3 = (unsigned char) on_failure_jump;
5857 } 5839 }
5858 DEBUG_STATEMENT (debug -= 2); 5840 DEBUG_STATEMENT (debug -= 2);
@@ -5864,9 +5846,9 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5864 unconditional_jump: 5846 unconditional_jump:
5865 IMMEDIATE_QUIT_CHECK; 5847 IMMEDIATE_QUIT_CHECK;
5866 EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ 5848 EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */
5867 DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); 5849 DEBUG_PRINT ("EXECUTING jump %d ", mcnt);
5868 p += mcnt; /* Do the jump. */ 5850 p += mcnt; /* Do the jump. */
5869 DEBUG_PRINT2 ("(to %p).\n", p); 5851 DEBUG_PRINT ("(to %p).\n", p);
5870 break; 5852 break;
5871 5853
5872 5854
@@ -5875,7 +5857,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5875 case succeed_n: 5857 case succeed_n:
5876 /* Signedness doesn't matter since we only compare MCNT to 0. */ 5858 /* Signedness doesn't matter since we only compare MCNT to 0. */
5877 EXTRACT_NUMBER (mcnt, p + 2); 5859 EXTRACT_NUMBER (mcnt, p + 2);
5878 DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); 5860 DEBUG_PRINT ("EXECUTING succeed_n %d.\n", mcnt);
5879 5861
5880 /* Originally, mcnt is how many times we HAVE to succeed. */ 5862 /* Originally, mcnt is how many times we HAVE to succeed. */
5881 if (mcnt != 0) 5863 if (mcnt != 0)
@@ -5894,7 +5876,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5894 case jump_n: 5876 case jump_n:
5895 /* Signedness doesn't matter since we only compare MCNT to 0. */ 5877 /* Signedness doesn't matter since we only compare MCNT to 0. */
5896 EXTRACT_NUMBER (mcnt, p + 2); 5878 EXTRACT_NUMBER (mcnt, p + 2);
5897 DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); 5879 DEBUG_PRINT ("EXECUTING jump_n %d.\n", mcnt);
5898 5880
5899 /* Originally, this is how many times we CAN jump. */ 5881 /* Originally, this is how many times we CAN jump. */
5900 if (mcnt != 0) 5882 if (mcnt != 0)
@@ -5913,14 +5895,14 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5913 case set_number_at: 5895 case set_number_at:
5914 { 5896 {
5915 unsigned char *p2; /* Location of the counter. */ 5897 unsigned char *p2; /* Location of the counter. */
5916 DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); 5898 DEBUG_PRINT ("EXECUTING set_number_at.\n");
5917 5899
5918 EXTRACT_NUMBER_AND_INCR (mcnt, p); 5900 EXTRACT_NUMBER_AND_INCR (mcnt, p);
5919 /* Here, we discard `const', making re_match non-reentrant. */ 5901 /* Here, we discard `const', making re_match non-reentrant. */
5920 p2 = (unsigned char*) p + mcnt; 5902 p2 = (unsigned char*) p + mcnt;
5921 /* Signedness doesn't matter since we only copy MCNT's bits . */ 5903 /* Signedness doesn't matter since we only copy MCNT's bits . */
5922 EXTRACT_NUMBER_AND_INCR (mcnt, p); 5904 EXTRACT_NUMBER_AND_INCR (mcnt, p);
5923 DEBUG_PRINT3 (" Setting %p to %d.\n", p2, mcnt); 5905 DEBUG_PRINT (" Setting %p to %d.\n", p2, mcnt);
5924 PUSH_NUMBER (p2, mcnt); 5906 PUSH_NUMBER (p2, mcnt);
5925 break; 5907 break;
5926 } 5908 }
@@ -5929,7 +5911,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5929 case notwordbound: 5911 case notwordbound:
5930 { 5912 {
5931 boolean not = (re_opcode_t) *(p - 1) == notwordbound; 5913 boolean not = (re_opcode_t) *(p - 1) == notwordbound;
5932 DEBUG_PRINT2 ("EXECUTING %swordbound.\n", not?"not":""); 5914 DEBUG_PRINT ("EXECUTING %swordbound.\n", not ? "not" : "");
5933 5915
5934 /* We SUCCEED (or FAIL) in one of the following cases: */ 5916 /* We SUCCEED (or FAIL) in one of the following cases: */
5935 5917
@@ -5971,7 +5953,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
5971 } 5953 }
5972 5954
5973 case wordbeg: 5955 case wordbeg:
5974 DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); 5956 DEBUG_PRINT ("EXECUTING wordbeg.\n");
5975 5957
5976 /* We FAIL in one of the following cases: */ 5958 /* We FAIL in one of the following cases: */
5977 5959
@@ -6016,7 +5998,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
6016 break; 5998 break;
6017 5999
6018 case wordend: 6000 case wordend:
6019 DEBUG_PRINT1 ("EXECUTING wordend.\n"); 6001 DEBUG_PRINT ("EXECUTING wordend.\n");
6020 6002
6021 /* We FAIL in one of the following cases: */ 6003 /* We FAIL in one of the following cases: */
6022 6004
@@ -6061,7 +6043,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
6061 break; 6043 break;
6062 6044
6063 case symbeg: 6045 case symbeg:
6064 DEBUG_PRINT1 ("EXECUTING symbeg.\n"); 6046 DEBUG_PRINT ("EXECUTING symbeg.\n");
6065 6047
6066 /* We FAIL in one of the following cases: */ 6048 /* We FAIL in one of the following cases: */
6067 6049
@@ -6104,7 +6086,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
6104 break; 6086 break;
6105 6087
6106 case symend: 6088 case symend:
6107 DEBUG_PRINT1 ("EXECUTING symend.\n"); 6089 DEBUG_PRINT ("EXECUTING symend.\n");
6108 6090
6109 /* We FAIL in one of the following cases: */ 6091 /* We FAIL in one of the following cases: */
6110 6092
@@ -6151,7 +6133,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
6151 { 6133 {
6152 boolean not = (re_opcode_t) *(p - 1) == notsyntaxspec; 6134 boolean not = (re_opcode_t) *(p - 1) == notsyntaxspec;
6153 mcnt = *p++; 6135 mcnt = *p++;
6154 DEBUG_PRINT3 ("EXECUTING %ssyntaxspec %d.\n", not?"not":"", mcnt); 6136 DEBUG_PRINT ("EXECUTING %ssyntaxspec %d.\n", not ? "not" : "",
6137 mcnt);
6155 PREFETCH (); 6138 PREFETCH ();
6156#ifdef emacs 6139#ifdef emacs
6157 { 6140 {
@@ -6174,19 +6157,19 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
6174 6157
6175#ifdef emacs 6158#ifdef emacs
6176 case before_dot: 6159 case before_dot:
6177 DEBUG_PRINT1 ("EXECUTING before_dot.\n"); 6160 DEBUG_PRINT ("EXECUTING before_dot.\n");
6178 if (PTR_BYTE_POS (d) >= PT_BYTE) 6161 if (PTR_BYTE_POS (d) >= PT_BYTE)
6179 goto fail; 6162 goto fail;
6180 break; 6163 break;
6181 6164
6182 case at_dot: 6165 case at_dot:
6183 DEBUG_PRINT1 ("EXECUTING at_dot.\n"); 6166 DEBUG_PRINT ("EXECUTING at_dot.\n");
6184 if (PTR_BYTE_POS (d) != PT_BYTE) 6167 if (PTR_BYTE_POS (d) != PT_BYTE)
6185 goto fail; 6168 goto fail;
6186 break; 6169 break;
6187 6170
6188 case after_dot: 6171 case after_dot:
6189 DEBUG_PRINT1 ("EXECUTING after_dot.\n"); 6172 DEBUG_PRINT ("EXECUTING after_dot.\n");
6190 if (PTR_BYTE_POS (d) <= PT_BYTE) 6173 if (PTR_BYTE_POS (d) <= PT_BYTE)
6191 goto fail; 6174 goto fail;
6192 break; 6175 break;
@@ -6196,8 +6179,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
6196 { 6179 {
6197 boolean not = (re_opcode_t) *(p - 1) == notcategoryspec; 6180 boolean not = (re_opcode_t) *(p - 1) == notcategoryspec;
6198 mcnt = *p++; 6181 mcnt = *p++;
6199 DEBUG_PRINT3 ("EXECUTING %scategoryspec %d.\n", 6182 DEBUG_PRINT ("EXECUTING %scategoryspec %d.\n",
6200 not?"not":"", mcnt); 6183 not ? "not" : "", mcnt);
6201 PREFETCH (); 6184 PREFETCH ();
6202 6185
6203 { 6186 {
@@ -6226,7 +6209,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
6226 { 6209 {
6227 re_char *str, *pat; 6210 re_char *str, *pat;
6228 /* A restart point is known. Restore to that state. */ 6211 /* A restart point is known. Restore to that state. */
6229 DEBUG_PRINT1 ("\nFAIL:\n"); 6212 DEBUG_PRINT ("\nFAIL:\n");
6230 POP_FAILURE_POINT (str, pat); 6213 POP_FAILURE_POINT (str, pat);
6231 switch (*pat++) 6214 switch (*pat++)
6232 { 6215 {
@@ -6271,7 +6254,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const re_char *string1,
6271 FREE_VARIABLES (); 6254 FREE_VARIABLES ();
6272 6255
6273 return -1; /* Failure to match. */ 6256 return -1; /* Failure to match. */
6274} /* re_match_2 */ 6257}
6275 6258
6276/* Subroutine definitions for re_match_2. */ 6259/* Subroutine definitions for re_match_2. */
6277 6260
diff --git a/src/unexelf.c b/src/unexelf.c
index d3659404f9c..4e50bb86367 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -388,16 +388,19 @@ temacs:
388#include <config.h> 388#include <config.h>
389#include <unexec.h> 389#include <unexec.h>
390 390
391extern void fatal (const char *msgid, ...); 391extern _Noreturn void fatal (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
392 392
393#include <sys/types.h> 393#include <errno.h>
394#include <fcntl.h>
395#include <limits.h>
396#include <memory.h>
397#include <stdbool.h>
394#include <stdint.h> 398#include <stdint.h>
395#include <stdio.h> 399#include <stdio.h>
396#include <sys/stat.h> 400#include <sys/stat.h>
397#include <memory.h> 401#include <sys/types.h>
398#include <errno.h>
399#include <unistd.h> 402#include <unistd.h>
400#include <fcntl.h> 403
401#if !defined (__NetBSD__) && !defined (__OpenBSD__) 404#if !defined (__NetBSD__) && !defined (__OpenBSD__)
402#include <elf.h> 405#include <elf.h>
403#endif /* not __NetBSD__ and not __OpenBSD__ */ 406#endif /* not __NetBSD__ and not __OpenBSD__ */
@@ -519,6 +522,18 @@ typedef struct {
519# define ElfW(type) ElfExpandBitsW (ELFSIZE, type) 522# define ElfW(type) ElfExpandBitsW (ELFSIZE, type)
520#endif 523#endif
521 524
525/* The code often converts ElfW (Half) values like e_shentsize to ptrdiff_t;
526 check that this doesn't lose information. */
527#include <intprops.h>
528#include <verify.h>
529verify ((! TYPE_SIGNED (ElfW (Half))
530 || PTRDIFF_MIN <= TYPE_MINIMUM (ElfW (Half)))
531 && TYPE_MAXIMUM (ElfW (Half)) <= PTRDIFF_MAX);
532
533#ifdef UNEXELF_DEBUG
534# define DEBUG_LOG(expr) fprintf (stderr, #expr " 0x%jx\n", (uintmax_t) (expr))
535#endif
536
522/* Get the address of a particular section or program header entry, 537/* Get the address of a particular section or program header entry,
523 * accounting for the size of the entries. 538 * accounting for the size of the entries.
524 */ 539 */
@@ -546,17 +561,21 @@ typedef struct {
546 Apr 23, 1996 561 Apr 23, 1996
547 */ 562 */
548 563
564static void *
565entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
566{
567 char *h = section_h;
568 return h + idx * entsize;
569}
570
549#define OLD_SECTION_H(n) \ 571#define OLD_SECTION_H(n) \
550 (*(ElfW (Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) 572 (*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize))
551#define NEW_SECTION_H(n) \ 573#define NEW_SECTION_H(n) \
552 (*(ElfW (Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) 574 (*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize))
553#define NEW_PROGRAM_H(n) \ 575#define NEW_PROGRAM_H(n) \
554 (*(ElfW (Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) 576 (*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phentsize))
555 577
556#define PATCH_INDEX(n) \ 578#define PATCH_INDEX(n) ((n) += old_bss_index <= (n))
557 do { \
558 if ((int) (n) >= old_bss_index) \
559 (n)++; } while (0)
560typedef unsigned char byte; 579typedef unsigned char byte;
561 580
562/* Round X up to a multiple of Y. */ 581/* Round X up to a multiple of Y. */
@@ -564,7 +583,7 @@ typedef unsigned char byte;
564static ElfW (Addr) 583static ElfW (Addr)
565round_up (ElfW (Addr) x, ElfW (Addr) y) 584round_up (ElfW (Addr) x, ElfW (Addr) y)
566{ 585{
567 int rem = x % y; 586 ElfW (Addr) rem = x % y;
568 if (rem == 0) 587 if (rem == 0)
569 return x; 588 return x;
570 return x - rem + y; 589 return x - rem + y;
@@ -575,33 +594,28 @@ round_up (ElfW (Addr) x, ElfW (Addr) y)
575 about the file we are looking in. 594 about the file we are looking in.
576 595
577 If we don't find the section NAME, that is a fatal error 596 If we don't find the section NAME, that is a fatal error
578 if NOERROR is 0; we return -1 if NOERROR is nonzero. */ 597 if NOERROR is false; return -1 if NOERROR is true. */
579 598
580static int 599static ptrdiff_t
581find_section (const char *name, const char *section_names, const char *file_name, 600find_section (const char *name, const char *section_names, const char *file_name,
582 ElfW (Ehdr) *old_file_h, ElfW (Shdr) *old_section_h, int noerror) 601 ElfW (Ehdr) *old_file_h, ElfW (Shdr) *old_section_h,
602 bool noerror)
583{ 603{
584 int idx; 604 ptrdiff_t idx;
585 605
586 for (idx = 1; idx < old_file_h->e_shnum; idx++) 606 for (idx = 1; idx < old_file_h->e_shnum; idx++)
587 { 607 {
588#ifdef DEBUG 608 char const *found_name = section_names + OLD_SECTION_H (idx).sh_name;
589 fprintf (stderr, "Looking for %s - found %s\n", name, 609#ifdef UNEXELF_DEBUG
590 section_names + OLD_SECTION_H (idx).sh_name); 610 fprintf (stderr, "Looking for %s - found %s\n", name, found_name);
591#endif 611#endif
592 if (!strcmp (section_names + OLD_SECTION_H (idx).sh_name, 612 if (strcmp (name, found_name) == 0)
593 name)) 613 return idx;
594 break;
595 }
596 if (idx == old_file_h->e_shnum)
597 {
598 if (noerror)
599 return -1;
600 else
601 fatal ("Can't find %s in %s.\n", name, file_name);
602 } 614 }
603 615
604 return idx; 616 if (! noerror)
617 fatal ("Can't find %s in %s", name, file_name);
618 return -1;
605} 619}
606 620
607/* **************************************************************** 621/* ****************************************************************
@@ -616,11 +630,9 @@ find_section (const char *name, const char *section_names, const char *file_name
616void 630void
617unexec (const char *new_name, const char *old_name) 631unexec (const char *new_name, const char *old_name)
618{ 632{
619 int new_file, old_file, new_file_size; 633 int new_file, old_file;
620 634 off_t new_file_size;
621#if defined (emacs) || !defined (DEBUG)
622 void *new_break; 635 void *new_break;
623#endif
624 636
625 /* Pointers to the base of the image of the two files. */ 637 /* Pointers to the base of the image of the two files. */
626 caddr_t old_base, new_base; 638 caddr_t old_base, new_base;
@@ -647,14 +659,15 @@ unexec (const char *new_name, const char *old_name)
647 ElfW (Off) old_bss_offset; 659 ElfW (Off) old_bss_offset;
648 ElfW (Word) new_data2_incr; 660 ElfW (Word) new_data2_incr;
649 661
650 int n, nn; 662 ptrdiff_t n, nn;
651 int old_bss_index, old_sbss_index, old_plt_index; 663 ptrdiff_t old_bss_index, old_sbss_index, old_plt_index;
652 int old_data_index, new_data2_index; 664 ptrdiff_t old_data_index, new_data2_index;
653#if defined _SYSTYPE_SYSV || defined __sgi 665#if defined _SYSTYPE_SYSV || defined __sgi
654 int old_mdebug_index; 666 ptrdiff_t old_mdebug_index;
655#endif 667#endif
656 struct stat stat_buf; 668 struct stat stat_buf;
657 int old_file_size; 669 off_t old_file_size;
670 int mask;
658 671
659 /* Open the old file, allocate a buffer of the right size, and read 672 /* Open the old file, allocate a buffer of the right size, and read
660 in the file contents. */ 673 in the file contents. */
@@ -662,15 +675,15 @@ unexec (const char *new_name, const char *old_name)
662 old_file = open (old_name, O_RDONLY); 675 old_file = open (old_name, O_RDONLY);
663 676
664 if (old_file < 0) 677 if (old_file < 0)
665 fatal ("Can't open %s for reading: errno %d\n", old_name, errno); 678 fatal ("Can't open %s for reading: %s", old_name, strerror (errno));
666 679
667 if (fstat (old_file, &stat_buf) == -1) 680 if (fstat (old_file, &stat_buf) != 0)
668 fatal ("Can't fstat (%s): errno %d\n", old_name, errno); 681 fatal ("Can't fstat (%s): %s", old_name, strerror (errno));
669 682
670#if MAP_ANON == 0 683#if MAP_ANON == 0
671 mmap_fd = open ("/dev/zero", O_RDONLY); 684 mmap_fd = open ("/dev/zero", O_RDONLY);
672 if (mmap_fd < 0) 685 if (mmap_fd < 0)
673 fatal ("Can't open /dev/zero for reading: errno %d\n", errno, 0); 686 fatal ("Can't open /dev/zero for reading: %s", strerror (errno));
674#endif 687#endif
675 688
676 /* We cannot use malloc here because that may use sbrk. If it does, 689 /* We cannot use malloc here because that may use sbrk. If it does,
@@ -678,13 +691,15 @@ unexec (const char *new_name, const char *old_name)
678 extra careful to use the correct value of sbrk(0) after 691 extra careful to use the correct value of sbrk(0) after
679 allocating all buffers in the code below, which we aren't. */ 692 allocating all buffers in the code below, which we aren't. */
680 old_file_size = stat_buf.st_size; 693 old_file_size = stat_buf.st_size;
694 if (! (0 <= old_file_size && old_file_size <= SIZE_MAX))
695 fatal ("File size out of range");
681 old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE, 696 old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE,
682 MAP_ANON | MAP_PRIVATE, mmap_fd, 0); 697 MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
683 if (old_base == MAP_FAILED) 698 if (old_base == MAP_FAILED)
684 fatal ("Can't allocate buffer for %s\n", old_name, 0); 699 fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
685 700
686 if (read (old_file, old_base, stat_buf.st_size) != stat_buf.st_size) 701 if (read (old_file, old_base, old_file_size) != old_file_size)
687 fatal ("Didn't read all of %s: errno %d\n", old_name, errno); 702 fatal ("Didn't read all of %s: %s", old_name, strerror (errno));
688 703
689 /* Get pointers to headers & section names */ 704 /* Get pointers to headers & section names */
690 705
@@ -755,12 +770,8 @@ unexec (const char *new_name, const char *old_name)
755 old_data_index = find_section (".data", old_section_names, 770 old_data_index = find_section (".data", old_section_names,
756 old_name, old_file_h, old_section_h, 0); 771 old_name, old_file_h, old_section_h, 0);
757 772
758#if defined (emacs) || !defined (DEBUG)
759 new_break = sbrk (0); 773 new_break = sbrk (0);
760 new_bss_addr = (ElfW (Addr)) new_break; 774 new_bss_addr = (ElfW (Addr)) new_break;
761#else
762 new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
763#endif
764 new_data2_addr = old_bss_addr; 775 new_data2_addr = old_bss_addr;
765 new_data2_size = new_bss_addr - old_bss_addr; 776 new_data2_size = new_bss_addr - old_bss_addr;
766 new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset 777 new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset
@@ -771,38 +782,38 @@ unexec (const char *new_name, const char *old_name)
771 section) was unaligned. */ 782 section) was unaligned. */
772 new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset); 783 new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset);
773 784
774#ifdef DEBUG 785#ifdef UNEXELF_DEBUG
775 fprintf (stderr, "old_bss_index %d\n", old_bss_index); 786 fprintf (stderr, "old_bss_index %td\n", old_bss_index);
776 fprintf (stderr, "old_bss_addr %x\n", old_bss_addr); 787 DEBUG_LOG (old_bss_addr);
777 fprintf (stderr, "old_bss_size %x\n", old_bss_size); 788 DEBUG_LOG (old_bss_size);
778 fprintf (stderr, "old_bss_offset %x\n", old_bss_offset); 789 DEBUG_LOG (old_bss_offset);
779 fprintf (stderr, "new_bss_addr %x\n", new_bss_addr); 790 DEBUG_LOG (new_bss_addr);
780 fprintf (stderr, "new_data2_addr %x\n", new_data2_addr); 791 DEBUG_LOG (new_data2_addr);
781 fprintf (stderr, "new_data2_size %x\n", new_data2_size); 792 DEBUG_LOG (new_data2_size);
782 fprintf (stderr, "new_data2_offset %x\n", new_data2_offset); 793 DEBUG_LOG (new_data2_offset);
783 fprintf (stderr, "new_data2_incr %x\n", new_data2_incr); 794 DEBUG_LOG (new_data2_incr);
784#endif 795#endif
785 796
786 if ((uintptr_t) new_bss_addr < (uintptr_t) old_bss_addr + old_bss_size) 797 if (new_bss_addr < old_bss_addr + old_bss_size)
787 fatal (".bss shrank when undumping???\n", 0, 0); 798 fatal (".bss shrank when undumping");
788 799
789 /* Set the output file to the right size. Allocate a buffer to hold 800 /* Set the output file to the right size. Allocate a buffer to hold
790 the image of the new file. Set pointers to various interesting 801 the image of the new file. Set pointers to various interesting
791 objects. stat_buf still has old_file data. */ 802 objects. */
792 803
793 new_file = open (new_name, O_RDWR | O_CREAT, 0666); 804 new_file = open (new_name, O_RDWR | O_CREAT, 0666);
794 if (new_file < 0) 805 if (new_file < 0)
795 fatal ("Can't creat (%s): errno %d\n", new_name, errno); 806 fatal ("Can't creat (%s): %s", new_name, strerror (errno));
796 807
797 new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_incr; 808 new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_incr;
798 809
799 if (ftruncate (new_file, new_file_size)) 810 if (ftruncate (new_file, new_file_size))
800 fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); 811 fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
801 812
802 new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE, 813 new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE,
803 MAP_ANON | MAP_PRIVATE, mmap_fd, 0); 814 MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
804 if (new_base == MAP_FAILED) 815 if (new_base == MAP_FAILED)
805 fatal ("Can't allocate buffer for %s\n", old_name, 0); 816 fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
806 817
807 new_file_h = (ElfW (Ehdr) *) new_base; 818 new_file_h = (ElfW (Ehdr) *) new_base;
808 new_program_h = (ElfW (Phdr) *) ((byte *) new_base + old_file_h->e_phoff); 819 new_program_h = (ElfW (Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
@@ -825,11 +836,11 @@ unexec (const char *new_name, const char *old_name)
825 new_file_h->e_shoff += new_data2_incr; 836 new_file_h->e_shoff += new_data2_incr;
826 new_file_h->e_shnum += 1; 837 new_file_h->e_shnum += 1;
827 838
828#ifdef DEBUG 839#ifdef UNEXELF_DEBUG
829 fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff); 840 DEBUG_LOG (old_file_h->e_shoff);
830 fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum); 841 fprintf (stderr, "Old section count %td\n", (ptrdiff_t) old_file_h->e_shnum);
831 fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff); 842 DEBUG_LOG (new_file_h->e_shoff);
832 fprintf (stderr, "New section count %d\n", new_file_h->e_shnum); 843 fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum);
833#endif 844#endif
834 845
835 /* Fix up a new program header. Extend the writable data segment so 846 /* Fix up a new program header. Extend the writable data segment so
@@ -839,7 +850,7 @@ unexec (const char *new_name, const char *old_name)
839 to adjust the offset and address of any segment that is above 850 to adjust the offset and address of any segment that is above
840 data2, just in case we decide to allow this later. */ 851 data2, just in case we decide to allow this later. */
841 852
842 for (n = new_file_h->e_phnum - 1; n >= 0; n--) 853 for (n = new_file_h->e_phnum; --n >= 0; )
843 { 854 {
844 /* Compute maximum of all requirements for alignment of section. */ 855 /* Compute maximum of all requirements for alignment of section. */
845 ElfW (Word) alignment = (NEW_PROGRAM_H (n)).p_align; 856 ElfW (Word) alignment = (NEW_PROGRAM_H (n)).p_align;
@@ -857,7 +868,7 @@ unexec (const char *new_name, const char *old_name)
857 > (old_sbss_index == -1 868 > (old_sbss_index == -1
858 ? old_bss_addr 869 ? old_bss_addr
859 : round_up (old_bss_addr, alignment))) 870 : round_up (old_bss_addr, alignment)))
860 fatal ("Program segment above .bss in %s\n", old_name, 0); 871 fatal ("Program segment above .bss in %s", old_name);
861 872
862 if (NEW_PROGRAM_H (n).p_type == PT_LOAD 873 if (NEW_PROGRAM_H (n).p_type == PT_LOAD
863 && (round_up ((NEW_PROGRAM_H (n)).p_vaddr 874 && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
@@ -867,7 +878,7 @@ unexec (const char *new_name, const char *old_name)
867 break; 878 break;
868 } 879 }
869 if (n < 0) 880 if (n < 0)
870 fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); 881 fatal ("Couldn't find segment next to .bss in %s", old_name);
871 882
872 /* Make sure that the size includes any padding before the old .bss 883 /* Make sure that the size includes any padding before the old .bss
873 section. */ 884 section. */
@@ -875,7 +886,7 @@ unexec (const char *new_name, const char *old_name)
875 NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; 886 NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
876 887
877#if 0 /* Maybe allow section after data2 - does this ever happen? */ 888#if 0 /* Maybe allow section after data2 - does this ever happen? */
878 for (n = new_file_h->e_phnum - 1; n >= 0; n--) 889 for (n = new_file_h->e_phnum; --n >= 0; )
879 { 890 {
880 if (NEW_PROGRAM_H (n).p_vaddr 891 if (NEW_PROGRAM_H (n).p_vaddr
881 && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr) 892 && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
@@ -894,7 +905,7 @@ unexec (const char *new_name, const char *old_name)
894 905
895 /* Walk through all section headers, insert the new data2 section right 906 /* Walk through all section headers, insert the new data2 section right
896 before the new bss section. */ 907 before the new bss section. */
897 for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) 908 for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
898 { 909 {
899 caddr_t src; 910 caddr_t src;
900 /* If it is (s)bss section, insert the new data2 section before it. */ 911 /* If it is (s)bss section, insert the new data2 section before it. */
@@ -1076,8 +1087,9 @@ temacs:
1076 if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG 1087 if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG
1077 && old_mdebug_index != -1) 1088 && old_mdebug_index != -1)
1078 { 1089 {
1079 int diff = NEW_SECTION_H (nn).sh_offset 1090 ptrdiff_t new_offset = NEW_SECTION_H (nn).sh_offset;
1080 - OLD_SECTION_H (old_mdebug_index).sh_offset; 1091 ptrdiff_t old_offset = OLD_SECTION_H (old_mdebug_index).sh_offset;
1092 ptrdiff_t diff = new_offset - old_offset;
1081 HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base); 1093 HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base);
1082 1094
1083 if (diff) 1095 if (diff)
@@ -1157,7 +1169,7 @@ temacs:
1157 || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) 1169 || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
1158 { 1170 {
1159 ElfW (Shdr) *spt = &NEW_SECTION_H (nn); 1171 ElfW (Shdr) *spt = &NEW_SECTION_H (nn);
1160 unsigned int num = spt->sh_size / spt->sh_entsize; 1172 ptrdiff_t num = spt->sh_size / spt->sh_entsize;
1161 ElfW (Sym) * sym = (ElfW (Sym) *) (NEW_SECTION_H (nn).sh_offset + 1173 ElfW (Sym) * sym = (ElfW (Sym) *) (NEW_SECTION_H (nn).sh_offset +
1162 new_base); 1174 new_base);
1163 for (; num--; sym++) 1175 for (; num--; sym++)
@@ -1173,7 +1185,7 @@ temacs:
1173 } 1185 }
1174 1186
1175 /* Update the symbol values of _edata and _end. */ 1187 /* Update the symbol values of _edata and _end. */
1176 for (n = new_file_h->e_shnum - 1; n; n--) 1188 for (n = new_file_h->e_shnum; 0 < --n; )
1177 { 1189 {
1178 byte *symnames; 1190 byte *symnames;
1179 ElfW (Sym) *symp, *symendp; 1191 ElfW (Sym) *symp, *symendp;
@@ -1233,7 +1245,7 @@ temacs:
1233 1245
1234 /* This loop seeks out relocation sections for the data section, so 1246 /* This loop seeks out relocation sections for the data section, so
1235 that it can undo relocations performed by the runtime linker. */ 1247 that it can undo relocations performed by the runtime linker. */
1236 for (n = new_file_h->e_shnum - 1; n; n--) 1248 for (n = new_file_h->e_shnum; 0 < --n; )
1237 { 1249 {
1238 ElfW (Shdr) section = NEW_SECTION_H (n); 1250 ElfW (Shdr) section = NEW_SECTION_H (n);
1239 1251
@@ -1293,8 +1305,8 @@ temacs:
1293 /* Write out new_file, and free the buffers. */ 1305 /* Write out new_file, and free the buffers. */
1294 1306
1295 if (write (new_file, new_base, new_file_size) != new_file_size) 1307 if (write (new_file, new_base, new_file_size) != new_file_size)
1296 fatal ("Didn't write %d bytes to %s: errno %d\n", 1308 fatal ("Didn't write %lu bytes to %s: %s",
1297 new_file_size, new_name, errno); 1309 (unsigned long) new_file_size, new_name, strerror (errno));
1298 munmap (old_base, old_file_size); 1310 munmap (old_base, old_file_size);
1299 munmap (new_base, new_file_size); 1311 munmap (new_base, new_file_size);
1300 1312
@@ -1304,18 +1316,18 @@ temacs:
1304 close (mmap_fd); 1316 close (mmap_fd);
1305#endif 1317#endif
1306 1318
1307 if (close (old_file)) 1319 if (close (old_file) != 0)
1308 fatal ("Can't close (%s): errno %d\n", old_name, errno); 1320 fatal ("Can't close (%s): %s", old_name, strerror (errno));
1309 1321
1310 if (close (new_file)) 1322 if (close (new_file) != 0)
1311 fatal ("Can't close (%s): errno %d\n", new_name, errno); 1323 fatal ("Can't close (%s): %s", new_name, strerror (errno));
1312 1324
1313 if (stat (new_name, &stat_buf) == -1) 1325 if (stat (new_name, &stat_buf) != 0)
1314 fatal ("Can't stat (%s): errno %d\n", new_name, errno); 1326 fatal ("Can't stat (%s): %s", new_name, strerror (errno));
1315 1327
1316 n = umask (777); 1328 mask = umask (777);
1317 umask (n); 1329 umask (mask);
1318 stat_buf.st_mode |= 0111 & ~n; 1330 stat_buf.st_mode |= 0111 & ~mask;
1319 if (chmod (new_name, stat_buf.st_mode) == -1) 1331 if (chmod (new_name, stat_buf.st_mode) != 0)
1320 fatal ("Can't chmod (%s): errno %d\n", new_name, errno); 1332 fatal ("Can't chmod (%s): %s", new_name, strerror (errno));
1321} 1333}
diff --git a/src/w32fns.c b/src/w32fns.c
index 0785e685e6a..d7ac0dd1a6c 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -3183,28 +3183,9 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
3183 form.ptCurrentPos.y = w32_system_caret_y; 3183 form.ptCurrentPos.y = w32_system_caret_y;
3184 3184
3185 form.rcArea.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, 0); 3185 form.rcArea.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, 0);
3186 3186 form.rcArea.top = WINDOW_TOP_EDGE_Y (w);
3187#ifdef ENABLE_CHECKING 3187 if (BUFFERP (w->contents))
3188 /* Temporary code to catch crashes in computing form.rcArea.top. */ 3188 form.rcArea.top += WINDOW_HEADER_LINE_HEIGHT (w);
3189 eassert (FRAMEP (w->frame));
3190 eassert (BUFFERP (w->contents));
3191 {
3192 int wmbp = WINDOW_MENU_BAR_P (w);
3193 int wtbp = WINDOW_TOOL_BAR_P (w);
3194 struct frame *wf = WINDOW_XFRAME (w);
3195 int fibw = FRAME_INTERNAL_BORDER_WIDTH (wf);
3196 int wtel = WINDOW_TOP_EDGE_LINE (w);
3197 int wflh = FRAME_LINE_HEIGHT (wf);
3198 int wwhlp= WINDOW_WANTS_HEADER_LINE_P (w);
3199 int chlh = CURRENT_HEADER_LINE_HEIGHT (w);
3200 int whlh = (wwhlp ? chlh : 0);
3201
3202 form.rcArea.top = ((wmbp || wtbp) ? 0 : fibw) + wtel * wflh + whlh;
3203 }
3204#else
3205 form.rcArea.top = (WINDOW_TOP_EDGE_Y (w)
3206 + WINDOW_HEADER_LINE_HEIGHT (w));
3207#endif
3208 form.rcArea.right = (WINDOW_BOX_RIGHT_EDGE_X (w) 3189 form.rcArea.right = (WINDOW_BOX_RIGHT_EDGE_X (w)
3209 - WINDOW_RIGHT_MARGIN_WIDTH (w) 3190 - WINDOW_RIGHT_MARGIN_WIDTH (w)
3210 - WINDOW_RIGHT_FRINGE_WIDTH (w)); 3191 - WINDOW_RIGHT_FRINGE_WIDTH (w));
diff --git a/src/xdisp.c b/src/xdisp.c
index 41214880a56..0a79e6fd891 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -794,6 +794,7 @@ static void set_iterator_to_next (struct it *, int);
794static void mark_window_display_accurate_1 (struct window *, int); 794static void mark_window_display_accurate_1 (struct window *, int);
795static int single_display_spec_string_p (Lisp_Object, Lisp_Object); 795static int single_display_spec_string_p (Lisp_Object, Lisp_Object);
796static int display_prop_string_p (Lisp_Object, Lisp_Object); 796static int display_prop_string_p (Lisp_Object, Lisp_Object);
797static int row_for_charpos_p (struct glyph_row *, ptrdiff_t);
797static int cursor_row_p (struct glyph_row *); 798static int cursor_row_p (struct glyph_row *);
798static int redisplay_mode_lines (Lisp_Object, int); 799static int redisplay_mode_lines (Lisp_Object, int);
799static char *decode_mode_spec_coding (Lisp_Object, char *, int); 800static char *decode_mode_spec_coding (Lisp_Object, char *, int);
@@ -1392,23 +1393,34 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1392 Lisp_Object cpos = make_number (charpos); 1393 Lisp_Object cpos = make_number (charpos);
1393 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil); 1394 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
1394 Lisp_Object string = string_from_display_spec (spec); 1395 Lisp_Object string = string_from_display_spec (spec);
1396 struct text_pos tpos;
1397 int replacing_spec_p;
1395 bool newline_in_string 1398 bool newline_in_string
1396 = (STRINGP (string) 1399 = (STRINGP (string)
1397 && memchr (SDATA (string), '\n', SBYTES (string))); 1400 && memchr (SDATA (string), '\n', SBYTES (string)));
1401
1402 SET_TEXT_POS (tpos, charpos, CHAR_TO_BYTE (charpos));
1403 replacing_spec_p
1404 = (!NILP (spec)
1405 && handle_display_spec (NULL, spec, Qnil, Qnil, &tpos,
1406 charpos, FRAME_WINDOW_P (it.f)));
1398 /* The tricky code below is needed because there's a 1407 /* The tricky code below is needed because there's a
1399 discrepancy between move_it_to and how we set cursor 1408 discrepancy between move_it_to and how we set cursor
1400 when the display line ends in a newline from a 1409 when PT is at the beginning of a portion of text
1401 display string. move_it_to will stop _after_ such 1410 covered by a display property or an overlay with a
1402 display strings, whereas set_cursor_from_row 1411 display property, or the display line ends in a
1403 conspires with cursor_row_p to place the cursor on 1412 newline from a display string. move_it_to will stop
1404 the first glyph produced from the display string. */ 1413 _after_ such display strings, whereas
1414 set_cursor_from_row conspires with cursor_row_p to
1415 place the cursor on the first glyph produced from the
1416 display string. */
1405 1417
1406 /* We have overshoot PT because it is covered by a 1418 /* We have overshoot PT because it is covered by a
1407 display property whose value is a string. If the 1419 display property that replaces the text it covers.
1408 string includes embedded newlines, we are also in the 1420 If the string includes embedded newlines, we are also
1409 wrong display line. Backtrack to the correct line, 1421 in the wrong display line. Backtrack to the correct
1410 where the display string begins. */ 1422 line, where the display property begins. */
1411 if (newline_in_string) 1423 if (replacing_spec_p)
1412 { 1424 {
1413 Lisp_Object startpos, endpos; 1425 Lisp_Object startpos, endpos;
1414 EMACS_INT start, end; 1426 EMACS_INT start, end;
@@ -1434,7 +1446,8 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1434 rightmost character on a line that is 1446 rightmost character on a line that is
1435 continued or word-wrapped. */ 1447 continued or word-wrapped. */
1436 if (it3.method == GET_FROM_BUFFER 1448 if (it3.method == GET_FROM_BUFFER
1437 && it3.c == '\n') 1449 && (it3.c == '\n'
1450 || FETCH_BYTE (IT_BYTEPOS (it3)) == '\n'))
1438 move_it_by_lines (&it3, 1); 1451 move_it_by_lines (&it3, 1);
1439 else if (move_it_in_display_line_to (&it3, -1, 1452 else if (move_it_in_display_line_to (&it3, -1,
1440 it3.current_x 1453 it3.current_x
@@ -1502,6 +1515,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1502 produced from the string, until we find the 1515 produced from the string, until we find the
1503 rightmost glyph not from the string. */ 1516 rightmost glyph not from the string. */
1504 if (it3_moved 1517 if (it3_moved
1518 && newline_in_string
1505 && IT_CHARPOS (it3) != charpos && EQ (it3.object, string)) 1519 && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
1506 { 1520 {
1507 struct glyph *g = it3.glyph_row->glyphs[TEXT_AREA] 1521 struct glyph *g = it3.glyph_row->glyphs[TEXT_AREA]
@@ -7153,6 +7167,7 @@ set_iterator_to_next (struct it *it, int reseat_p)
7153 else if (it->dpvec_char_len > 0) 7167 else if (it->dpvec_char_len > 0)
7154 { 7168 {
7155 if (it->method == GET_FROM_STRING 7169 if (it->method == GET_FROM_STRING
7170 && it->current.overlay_string_index >= 0
7156 && it->n_overlay_strings > 0) 7171 && it->n_overlay_strings > 0)
7157 it->ignore_overlay_strings_at_pos_p = 1; 7172 it->ignore_overlay_strings_at_pos_p = 1;
7158 it->len = it->dpvec_char_len; 7173 it->len = it->dpvec_char_len;
@@ -16895,10 +16910,9 @@ row_containing_pos (struct window *w, ptrdiff_t charpos,
16895 || (MATRIX_ROW_END_CHARPOS (row) == charpos 16910 || (MATRIX_ROW_END_CHARPOS (row) == charpos
16896 /* The end position of a row equals the start 16911 /* The end position of a row equals the start
16897 position of the next row. If CHARPOS is there, we 16912 position of the next row. If CHARPOS is there, we
16898 would rather display it in the next line, except 16913 would rather consider it displayed in the next
16899 when this line ends in ZV. */ 16914 line, except when this line ends in ZV. */
16900 && !row->ends_at_zv_p 16915 && !row_for_charpos_p (row, charpos)))
16901 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
16902 && charpos >= MATRIX_ROW_START_CHARPOS (row)) 16916 && charpos >= MATRIX_ROW_START_CHARPOS (row))
16903 { 16917 {
16904 struct glyph *g; 16918 struct glyph *g;
@@ -16906,10 +16920,10 @@ row_containing_pos (struct window *w, ptrdiff_t charpos,
16906 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)) 16920 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
16907 || (!best_row && !row->continued_p)) 16921 || (!best_row && !row->continued_p))
16908 return row; 16922 return row;
16909 /* In bidi-reordered rows, there could be several rows 16923 /* In bidi-reordered rows, there could be several rows whose
16910 occluding point, all of them belonging to the same 16924 edges surround CHARPOS, all of these rows belonging to
16911 continued line. We need to find the row which fits 16925 the same continued line. We need to find the row which
16912 CHARPOS the best. */ 16926 fits CHARPOS the best. */
16913 for (g = row->glyphs[TEXT_AREA]; 16927 for (g = row->glyphs[TEXT_AREA];
16914 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; 16928 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
16915 g++) 16929 g++)
@@ -18713,15 +18727,15 @@ highlight_trailing_whitespace (struct frame *f, struct glyph_row *row)
18713 18727
18714 18728
18715/* Value is non-zero if glyph row ROW should be 18729/* Value is non-zero if glyph row ROW should be
18716 used to hold the cursor. */ 18730 considered to hold the buffer position CHARPOS. */
18717 18731
18718static int 18732static int
18719cursor_row_p (struct glyph_row *row) 18733row_for_charpos_p (struct glyph_row *row, ptrdiff_t charpos)
18720{ 18734{
18721 int result = 1; 18735 int result = 1;
18722 18736
18723 if (PT == CHARPOS (row->end.pos) 18737 if (charpos == CHARPOS (row->end.pos)
18724 || PT == MATRIX_ROW_END_CHARPOS (row)) 18738 || charpos == MATRIX_ROW_END_CHARPOS (row))
18725 { 18739 {
18726 /* Suppose the row ends on a string. 18740 /* Suppose the row ends on a string.
18727 Unless the row is continued, that means it ends on a newline 18741 Unless the row is continued, that means it ends on a newline
@@ -18747,7 +18761,7 @@ cursor_row_p (struct glyph_row *row)
18747 if (STRINGP (glyph->object)) 18761 if (STRINGP (glyph->object))
18748 { 18762 {
18749 Lisp_Object prop 18763 Lisp_Object prop
18750 = Fget_char_property (make_number (PT), 18764 = Fget_char_property (make_number (charpos),
18751 Qdisplay, Qnil); 18765 Qdisplay, Qnil);
18752 result = 18766 result =
18753 (!NILP (prop) 18767 (!NILP (prop)
@@ -18801,6 +18815,15 @@ cursor_row_p (struct glyph_row *row)
18801 return result; 18815 return result;
18802} 18816}
18803 18817
18818/* Value is non-zero if glyph row ROW should be
18819 used to hold the cursor. */
18820
18821static int
18822cursor_row_p (struct glyph_row *row)
18823{
18824 return row_for_charpos_p (row, PT);
18825}
18826
18804 18827
18805 18828
18806/* Push the property PROP so that it will be rendered at the current 18829/* Push the property PROP so that it will be rendered at the current
diff --git a/src/xfns.c b/src/xfns.c
index f4c24cb09a0..46cd10e5f2f 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -59,6 +59,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
59 59
60#include "xsettings.h" 60#include "xsettings.h"
61 61
62#ifdef HAVE_XRANDR
63#include <X11/extensions/Xrandr.h>
64#endif
65#ifdef HAVE_XINERAMA
66#include <X11/extensions/Xinerama.h>
67#endif
68
62#ifdef USE_GTK 69#ifdef USE_GTK
63#include "gtkutil.h" 70#include "gtkutil.h"
64#endif 71#endif
@@ -126,6 +133,7 @@ extern LWLIB_ID widget_id_tick;
126static Lisp_Object Qsuppress_icon; 133static Lisp_Object Qsuppress_icon;
127static Lisp_Object Qundefined_color; 134static Lisp_Object Qundefined_color;
128static Lisp_Object Qcompound_text, Qcancel_timer; 135static Lisp_Object Qcompound_text, Qcancel_timer;
136static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource;
129Lisp_Object Qfont_param; 137Lisp_Object Qfont_param;
130 138
131#ifdef GLYPH_DEBUG 139#ifdef GLYPH_DEBUG
@@ -3791,6 +3799,575 @@ If omitted or nil, that stands for the selected frame's display. */)
3791 else 3799 else
3792 return Qnil; 3800 return Qnil;
3793} 3801}
3802
3803/* Store the geometry of the workarea on display DPYINFO into *RECT.
3804 Return false if and only if the workarea information cannot be
3805 obtained via the _NET_WORKAREA root window property. */
3806
3807#if ! GTK_CHECK_VERSION (3, 4, 0)
3808static bool
3809x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
3810{
3811 Display *dpy = dpyinfo->display;
3812 long offset, max_len;
3813 Atom target_type, actual_type;
3814 unsigned long actual_size, bytes_remaining;
3815 int rc, actual_format;
3816 unsigned char *tmp_data = NULL;
3817 bool result = false;
3818
3819 x_catch_errors (dpy);
3820 offset = 0;
3821 max_len = 1;
3822 target_type = XA_CARDINAL;
3823 rc = XGetWindowProperty (dpy, dpyinfo->root_window,
3824 dpyinfo->Xatom_net_current_desktop,
3825 offset, max_len, False, target_type,
3826 &actual_type, &actual_format, &actual_size,
3827 &bytes_remaining, &tmp_data);
3828 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
3829 && actual_format == 32 && actual_size == max_len)
3830 {
3831 long current_desktop = ((long *) tmp_data)[0];
3832
3833 XFree (tmp_data);
3834 tmp_data = NULL;
3835
3836 offset = 4 * current_desktop;
3837 max_len = 4;
3838 rc = XGetWindowProperty (dpy, dpyinfo->root_window,
3839 dpyinfo->Xatom_net_workarea,
3840 offset, max_len, False, target_type,
3841 &actual_type, &actual_format, &actual_size,
3842 &bytes_remaining, &tmp_data);
3843 if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
3844 && actual_format == 32 && actual_size == max_len)
3845 {
3846 long *values = (long *) tmp_data;
3847
3848 rect->x = values[0];
3849 rect->y = values[1];
3850 rect->width = values[2];
3851 rect->height = values[3];
3852
3853 XFree (tmp_data);
3854 tmp_data = NULL;
3855
3856 result = true;
3857 }
3858 }
3859 if (tmp_data)
3860 XFree (tmp_data);
3861 x_uncatch_errors ();
3862
3863 return result;
3864}
3865#endif
3866
3867#ifndef USE_GTK
3868
3869struct MonitorInfo {
3870 XRectangle geom, work;
3871 int mm_width, mm_height;
3872 char *name;
3873};
3874
3875#if defined HAVE_XINERAMA || defined HAVE_XRANDR
3876static void
3877free_monitors (struct MonitorInfo *monitors, int n_monitors)
3878{
3879 int i;
3880 for (i = 0; i < n_monitors; ++i)
3881 xfree (monitors[i].name);
3882 xfree (monitors);
3883}
3884#endif /* HAVE_XINERAMA || HAVE_XRANDR */
3885
3886
3887/* Return monitor number where F is "most" or closest to. */
3888static int
3889x_get_monitor_for_frame (struct frame *f,
3890 struct MonitorInfo *monitors,
3891 int n_monitors)
3892{
3893 XRectangle frect;
3894 int area = 0, dist = -1;
3895 int best_area = -1, best_dist = -1;
3896 int i;
3897
3898 if (n_monitors == 1) return 0;
3899 frect.x = f->left_pos;
3900 frect.y = f->top_pos;
3901 frect.width = FRAME_PIXEL_WIDTH (f);
3902 frect.height = FRAME_PIXEL_HEIGHT (f);
3903
3904 for (i = 0; i < n_monitors; ++i)
3905 {
3906 struct MonitorInfo *mi = &monitors[i];
3907 XRectangle res;
3908 int a = 0;
3909
3910 if (mi->geom.width == 0) continue;
3911
3912 if (x_intersect_rectangles (&mi->geom, &frect, &res))
3913 {
3914 a = res.width * res.height;
3915 if (a > area)
3916 {
3917 area = a;
3918 best_area = i;
3919 }
3920 }
3921
3922 if (a == 0 && area == 0)
3923 {
3924 int dx, dy, d;
3925 if (frect.x + frect.width < mi->geom.x)
3926 dx = mi->geom.x - frect.x + frect.width;
3927 else if (frect.x > mi->geom.x + mi->geom.width)
3928 dx = frect.x - mi->geom.x + mi->geom.width;
3929 else
3930 dx = 0;
3931 if (frect.y + frect.height < mi->geom.y)
3932 dy = mi->geom.y - frect.y + frect.height;
3933 else if (frect.y > mi->geom.y + mi->geom.height)
3934 dy = frect.y - mi->geom.y + mi->geom.height;
3935 else
3936 dy = 0;
3937
3938 d = dx*dx + dy*dy;
3939 if (dist == -1 || dist > d)
3940 {
3941 dist = d;
3942 best_dist = i;
3943 }
3944 }
3945 }
3946
3947 return best_area != -1 ? best_area : (best_dist != -1 ? best_dist : 0);
3948}
3949
3950static Lisp_Object
3951x_make_monitor_attribute_list (struct MonitorInfo *monitors,
3952 int n_monitors,
3953 int primary_monitor,
3954 struct x_display_info *dpyinfo,
3955 const char *source)
3956{
3957 Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
3958 Lisp_Object frame, rest, attributes_list = Qnil;
3959 Lisp_Object primary_monitor_attributes = Qnil;
3960 int i;
3961
3962 FOR_EACH_FRAME (rest, frame)
3963 {
3964 struct frame *f = XFRAME (frame);
3965
3966 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo
3967 && !EQ (frame, tip_frame))
3968 {
3969 i = x_get_monitor_for_frame (f, monitors, n_monitors);
3970 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
3971 }
3972 }
3973
3974 for (i = 0; i < n_monitors; ++i)
3975 {
3976 Lisp_Object geometry, workarea, attributes = Qnil;
3977 struct MonitorInfo *mi = &monitors[i];
3978
3979 if (mi->geom.width == 0) continue;
3980
3981 workarea = list4i (mi->work.x, mi->work.y,
3982 mi->work.width, mi->work.height);
3983 geometry = list4i (mi->geom.x, mi->geom.y,
3984 mi->geom.width, mi->geom.height);
3985 attributes = Fcons (Fcons (Qsource,
3986 make_string (source, strlen (source))),
3987 attributes);
3988 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
3989 attributes);
3990 attributes = Fcons (Fcons (Qmm_size,
3991 list2i (mi->mm_width, mi->mm_height)),
3992 attributes);
3993 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
3994 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
3995 if (mi->name)
3996 attributes = Fcons (Fcons (Qname, make_string (mi->name,
3997 strlen (mi->name))),
3998 attributes);
3999
4000 if (i == primary_monitor)
4001 primary_monitor_attributes = attributes;
4002 else
4003 attributes_list = Fcons (attributes, attributes_list);
4004 }
4005
4006 if (!NILP (primary_monitor_attributes))
4007 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
4008 return attributes_list;
4009}
4010
4011static Lisp_Object
4012x_get_monitor_attributes_fallback (struct x_display_info *dpyinfo)
4013{
4014 struct MonitorInfo monitor;
4015 XRectangle workarea_r;
4016
4017 /* Fallback: treat (possibly) multiple physical monitors as if they
4018 formed a single monitor as a whole. This should provide a
4019 consistent result at least on single monitor environments. */
4020 monitor.geom.x = monitor.geom.y = 0;
4021 monitor.geom.width = x_display_pixel_width (dpyinfo);
4022 monitor.geom.height = x_display_pixel_height (dpyinfo);
4023 monitor.mm_width = WidthMMOfScreen (dpyinfo->screen);
4024 monitor.mm_height = HeightMMOfScreen (dpyinfo->screen);
4025 monitor.name = xstrdup ("combined screen");
4026
4027 if (x_get_net_workarea (dpyinfo, &workarea_r))
4028 monitor.work = workarea_r;
4029 else
4030 monitor.work = monitor.geom;
4031 return x_make_monitor_attribute_list (&monitor, 1, 0, dpyinfo, "fallback");
4032}
4033
4034
4035#ifdef HAVE_XINERAMA
4036static Lisp_Object
4037x_get_monitor_attributes_xinerama (struct x_display_info *dpyinfo)
4038{
4039 int n_monitors, i;
4040 Lisp_Object attributes_list = Qnil;
4041 Display *dpy = dpyinfo->display;
4042 XineramaScreenInfo *info = XineramaQueryScreens (dpy, &n_monitors);
4043 struct MonitorInfo *monitors;
4044 double mm_width_per_pixel, mm_height_per_pixel;
4045
4046 if (! info || n_monitors == 0)
4047 {
4048 if (info)
4049 XFree (info);
4050 return attributes_list;
4051 }
4052
4053 mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
4054 / x_display_pixel_width (dpyinfo));
4055 mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
4056 / x_display_pixel_height (dpyinfo));
4057 monitors = (struct MonitorInfo *) xzalloc (n_monitors * sizeof (*monitors));
4058 for (i = 0; i < n_monitors; ++i)
4059 {
4060 struct MonitorInfo *mi = &monitors[i];
4061 XRectangle workarea_r;
4062
4063 mi->geom.x = info[i].x_org;
4064 mi->geom.y = info[i].y_org;
4065 mi->geom.width = info[i].width;
4066 mi->geom.height = info[i].height;
4067 mi->mm_width = mi->geom.width * mm_width_per_pixel + 0.5;
4068 mi->mm_height = mi->geom.height * mm_height_per_pixel + 0.5;
4069 mi->name = 0;
4070
4071 /* Xinerama usually have primary monitor first, just use that. */
4072 if (i == 0 && x_get_net_workarea (dpyinfo, &workarea_r))
4073 {
4074 mi->work = workarea_r;
4075 if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
4076 mi->work = mi->geom;
4077 }
4078 else
4079 mi->work = mi->geom;
4080 }
4081 XFree (info);
4082
4083 attributes_list = x_make_monitor_attribute_list (monitors,
4084 n_monitors,
4085 0,
4086 dpyinfo,
4087 "Xinerama");
4088 free_monitors (monitors, n_monitors);
4089 return attributes_list;
4090}
4091#endif /* HAVE_XINERAMA */
4092
4093
4094#ifdef HAVE_XRANDR
4095static Lisp_Object
4096x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo)
4097{
4098 Lisp_Object attributes_list = Qnil;
4099 XRRScreenResources *resources;
4100 Display *dpy = dpyinfo->display;
4101 int i, n_monitors, primary = -1;
4102 RROutput pxid = None;
4103 struct MonitorInfo *monitors;
4104
4105#ifdef HAVE_XRRGETSCREENRESOURCESCURRENT
4106 resources = XRRGetScreenResourcesCurrent (dpy, dpyinfo->root_window);
4107#else
4108 resources = XRRGetScreenResources (dpy, dpyinfo->root_window);
4109#endif
4110 if (! resources || resources->noutput == 0)
4111 {
4112 if (resources)
4113 XRRFreeScreenResources (resources);
4114 return Qnil;
4115 }
4116 n_monitors = resources->noutput;
4117 monitors = (struct MonitorInfo *) xzalloc (n_monitors * sizeof (*monitors));
4118
4119#ifdef HAVE_XRRGETOUTPUTPRIMARY
4120 pxid = XRRGetOutputPrimary (dpy, dpyinfo->root_window);
4121#endif
4122
4123 for (i = 0; i < n_monitors; ++i)
4124 {
4125 XRROutputInfo *info = XRRGetOutputInfo (dpy, resources,
4126 resources->outputs[i]);
4127 Connection conn = info ? info->connection : RR_Disconnected;
4128 RRCrtc id = info ? info->crtc : None;
4129
4130 if (strcmp (info->name, "default") == 0)
4131 {
4132 /* Non XRandr 1.2 driver, does not give useful data. */
4133 XRRFreeOutputInfo (info);
4134 XRRFreeScreenResources (resources);
4135 free_monitors (monitors, n_monitors);
4136 return Qnil;
4137 }
4138
4139 if (conn != RR_Disconnected && id != None)
4140 {
4141 XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, id);
4142 struct MonitorInfo *mi = &monitors[i];
4143 XRectangle workarea_r;
4144
4145 if (! crtc)
4146 {
4147 XRRFreeOutputInfo (info);
4148 continue;
4149 }
4150
4151 mi->geom.x = crtc->x;
4152 mi->geom.y = crtc->y;
4153 mi->geom.width = crtc->width;
4154 mi->geom.height = crtc->height;
4155 mi->mm_width = info->mm_width;
4156 mi->mm_height = info->mm_height;
4157 mi->name = xstrdup (info->name);
4158
4159 if (pxid != None && pxid == resources->outputs[i])
4160 primary = i;
4161 else if (primary == -1 && strcmp (info->name, "LVDS") == 0)
4162 primary = i;
4163
4164 if (i == primary && x_get_net_workarea (dpyinfo, &workarea_r))
4165 {
4166 mi->work= workarea_r;
4167 if (! x_intersect_rectangles (&mi->geom, &mi->work, &mi->work))
4168 mi->work = mi->geom;
4169 }
4170 else
4171 mi->work = mi->geom;
4172
4173 XRRFreeCrtcInfo (crtc);
4174 }
4175 XRRFreeOutputInfo (info);
4176 }
4177 XRRFreeScreenResources (resources);
4178
4179 attributes_list = x_make_monitor_attribute_list (monitors,
4180 n_monitors,
4181 primary,
4182 dpyinfo,
4183 "XRandr");
4184 free_monitors (monitors, n_monitors);
4185 return attributes_list;
4186}
4187#endif /* HAVE_XRANDR */
4188
4189static Lisp_Object
4190x_get_monitor_attributes (struct x_display_info *dpyinfo)
4191{
4192 Lisp_Object attributes_list = Qnil;
4193 Display *dpy = dpyinfo->display;
4194
4195#ifdef HAVE_XRANDR
4196 int xrr_event_base, xrr_error_base;
4197 bool xrr_ok = false;
4198 xrr_ok = XRRQueryExtension (dpy, &xrr_event_base, &xrr_error_base);
4199 if (xrr_ok)
4200 {
4201 int xrr_major, xrr_minor;
4202 XRRQueryVersion (dpy, &xrr_major, &xrr_minor);
4203 xrr_ok = (xrr_major == 1 && xrr_minor >= 2) || xrr_major > 1;
4204 }
4205
4206 if (xrr_ok)
4207 attributes_list = x_get_monitor_attributes_xrandr (dpyinfo);
4208#endif /* HAVE_XRANDR */
4209
4210#ifdef HAVE_XINERAMA
4211 if (NILP (attributes_list))
4212 {
4213 int xin_event_base, xin_error_base;
4214 bool xin_ok = false;
4215 xin_ok = XineramaQueryExtension (dpy, &xin_event_base, &xin_error_base);
4216 if (xin_ok && XineramaIsActive (dpy))
4217 attributes_list = x_get_monitor_attributes_xinerama (dpyinfo);
4218 }
4219#endif /* HAVE_XINERAMA */
4220
4221 if (NILP (attributes_list))
4222 attributes_list = x_get_monitor_attributes_fallback (dpyinfo);
4223
4224 return attributes_list;
4225}
4226
4227#endif /* !USE_GTK */
4228
4229DEFUN ("x-display-monitor-attributes-list", Fx_display_monitor_attributes_list,
4230 Sx_display_monitor_attributes_list,
4231 0, 1, 0,
4232 doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
4233
4234The optional argument TERMINAL specifies which display to ask about.
4235TERMINAL should be a terminal object, a frame or a display name (a string).
4236If omitted or nil, that stands for the selected frame's display.
4237
4238In addition to the standard attribute keys listed in
4239`display-monitor-attributes-list', the following keys are contained in
4240the attributes:
4241
4242 source -- String describing the source from which multi-monitor
4243 information is obtained, one of \"Gdk\", \"XRandr\",
4244 \"Xinerama\", or \"fallback\"
4245
4246Internal use only, use `display-monitor-attributes-list' instead. */)
4247 (Lisp_Object terminal)
4248{
4249 struct x_display_info *dpyinfo = check_x_display_info (terminal);
4250 Lisp_Object attributes_list = Qnil;
4251
4252#ifdef USE_GTK
4253 double mm_width_per_pixel, mm_height_per_pixel;
4254 GdkDisplay *gdpy;
4255 GdkScreen *gscreen;
4256 gint primary_monitor = 0, n_monitors, i;
4257 Lisp_Object primary_monitor_attributes = Qnil;
4258 Lisp_Object monitor_frames, rest, frame;
4259 static const char *source = "Gdk";
4260
4261 block_input ();
4262 mm_width_per_pixel = ((double) WidthMMOfScreen (dpyinfo->screen)
4263 / x_display_pixel_width (dpyinfo));
4264 mm_height_per_pixel = ((double) HeightMMOfScreen (dpyinfo->screen)
4265 / x_display_pixel_height (dpyinfo));
4266 gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
4267 gscreen = gdk_display_get_default_screen (gdpy);
4268#if GTK_CHECK_VERSION (2, 20, 0)
4269 primary_monitor = gdk_screen_get_primary_monitor (gscreen);
4270#endif
4271 n_monitors = gdk_screen_get_n_monitors (gscreen);
4272 monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
4273 FOR_EACH_FRAME (rest, frame)
4274 {
4275 struct frame *f = XFRAME (frame);
4276
4277 if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo
4278 && !EQ (frame, tip_frame))
4279 {
4280 GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
4281
4282 i = gdk_screen_get_monitor_at_window (gscreen, gwin);
4283 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
4284 }
4285 }
4286
4287 i = n_monitors;
4288 while (i-- > 0)
4289 {
4290 Lisp_Object geometry, workarea, attributes = Qnil;
4291 gint width_mm = -1, height_mm = -1;
4292 GdkRectangle rec;
4293
4294 attributes = Fcons (Fcons (Qsource,
4295 make_string (source, strlen (source))),
4296 attributes);
4297 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
4298 attributes);
4299
4300 gdk_screen_get_monitor_geometry (gscreen, i, &rec);
4301 geometry = list4i (rec.x, rec.y, rec.width, rec.height);
4302
4303#if GTK_CHECK_VERSION (2, 14, 0)
4304 width_mm = gdk_screen_get_monitor_width_mm (gscreen, i);
4305 height_mm = gdk_screen_get_monitor_height_mm (gscreen, i);
4306#endif
4307 if (width_mm < 0)
4308 width_mm = rec.width * mm_width_per_pixel + 0.5;
4309 if (height_mm < 0)
4310 height_mm = rec.height * mm_height_per_pixel + 0.5;
4311 attributes = Fcons (Fcons (Qmm_size,
4312 list2i (width_mm, height_mm)),
4313 attributes);
4314
4315#if GTK_CHECK_VERSION (3, 4, 0)
4316 gdk_screen_get_monitor_workarea (gscreen, i, &rec);
4317 workarea = list4i (rec.x, rec.y, rec.width, rec.height);
4318#else
4319 /* Emulate the behavior of GTK+ 3.4. */
4320 {
4321 XRectangle workarea_r;
4322
4323 workarea = Qnil;
4324 if (i == primary_monitor && x_get_net_workarea (dpyinfo, &workarea_r))
4325 {
4326 GdkRectangle work;
4327
4328 work.x = workarea_r.x;
4329 work.y = workarea_r.y;
4330 work.width = workarea_r.width;
4331 work.height = workarea_r.height;
4332 if (gdk_rectangle_intersect (&rec, &work, &work))
4333 workarea = list4i (work.x, work.y, work.width, work.height);
4334 }
4335 if (NILP (workarea))
4336 workarea = geometry;
4337 }
4338#endif
4339 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
4340
4341 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
4342#if GTK_CHECK_VERSION (2, 14, 0)
4343 {
4344 char *name = gdk_screen_get_monitor_plug_name (gscreen, i);
4345 if (name)
4346 attributes = Fcons (Fcons (Qname, make_string (name, strlen (name))),
4347 attributes);
4348 }
4349#endif
4350
4351 if (i == primary_monitor)
4352 primary_monitor_attributes = attributes;
4353 else
4354 attributes_list = Fcons (attributes, attributes_list);
4355 }
4356
4357 if (!NILP (primary_monitor_attributes))
4358 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
4359 unblock_input ();
4360#else /* not USE_GTK */
4361
4362 block_input ();
4363 attributes_list = x_get_monitor_attributes (dpyinfo);
4364 unblock_input ();
4365
4366#endif /* not USE_GTK */
4367
4368 return attributes_list;
4369}
4370
3794 4371
3795int 4372int
3796x_pixel_width (register struct frame *f) 4373x_pixel_width (register struct frame *f)
@@ -5701,6 +6278,11 @@ syms_of_xfns (void)
5701 DEFSYM (Qundefined_color, "undefined-color"); 6278 DEFSYM (Qundefined_color, "undefined-color");
5702 DEFSYM (Qcompound_text, "compound-text"); 6279 DEFSYM (Qcompound_text, "compound-text");
5703 DEFSYM (Qcancel_timer, "cancel-timer"); 6280 DEFSYM (Qcancel_timer, "cancel-timer");
6281 DEFSYM (Qgeometry, "geometry");
6282 DEFSYM (Qworkarea, "workarea");
6283 DEFSYM (Qmm_size, "mm-size");
6284 DEFSYM (Qframes, "frames");
6285 DEFSYM (Qsource, "source");
5704 DEFSYM (Qfont_param, "font-parameter"); 6286 DEFSYM (Qfont_param, "font-parameter");
5705 /* This is the end of symbol initialization. */ 6287 /* This is the end of symbol initialization. */
5706 6288
@@ -5864,6 +6446,7 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
5864 defsubr (&Sx_display_visual_class); 6446 defsubr (&Sx_display_visual_class);
5865 defsubr (&Sx_display_backing_store); 6447 defsubr (&Sx_display_backing_store);
5866 defsubr (&Sx_display_save_under); 6448 defsubr (&Sx_display_save_under);
6449 defsubr (&Sx_display_monitor_attributes_list);
5867 defsubr (&Sx_wm_set_size_hint); 6450 defsubr (&Sx_wm_set_size_hint);
5868 defsubr (&Sx_create_frame); 6451 defsubr (&Sx_create_frame);
5869 defsubr (&Sx_open_connection); 6452 defsubr (&Sx_open_connection);
diff --git a/src/xterm.c b/src/xterm.c
index e4a681031ef..7505aa3936b 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -9921,7 +9921,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
9921 9921
9922 dpy = DEFAULT_GDK_DISPLAY (); 9922 dpy = DEFAULT_GDK_DISPLAY ();
9923 9923
9924#if GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION <= 90 9924#if ! GTK_CHECK_VERSION (2, 90, 0)
9925 /* Load our own gtkrc if it exists. */ 9925 /* Load our own gtkrc if it exists. */
9926 { 9926 {
9927 const char *file = "~/.emacs.d/gtkrc"; 9927 const char *file = "~/.emacs.d/gtkrc";
@@ -10251,6 +10251,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
10251 { "_NET_WM_WINDOW_OPACITY", &dpyinfo->Xatom_net_wm_window_opacity }, 10251 { "_NET_WM_WINDOW_OPACITY", &dpyinfo->Xatom_net_wm_window_opacity },
10252 { "_NET_ACTIVE_WINDOW", &dpyinfo->Xatom_net_active_window }, 10252 { "_NET_ACTIVE_WINDOW", &dpyinfo->Xatom_net_active_window },
10253 { "_NET_FRAME_EXTENTS", &dpyinfo->Xatom_net_frame_extents }, 10253 { "_NET_FRAME_EXTENTS", &dpyinfo->Xatom_net_frame_extents },
10254 { "_NET_CURRENT_DESKTOP", &dpyinfo->Xatom_net_current_desktop },
10255 { "_NET_WORKAREA", &dpyinfo->Xatom_net_workarea },
10254 /* Session management */ 10256 /* Session management */
10255 { "SM_CLIENT_ID", &dpyinfo->Xatom_SM_CLIENT_ID }, 10257 { "SM_CLIENT_ID", &dpyinfo->Xatom_SM_CLIENT_ID },
10256 { "_XSETTINGS_SETTINGS", &dpyinfo->Xatom_xsettings_prop }, 10258 { "_XSETTINGS_SETTINGS", &dpyinfo->Xatom_xsettings_prop },
diff --git a/src/xterm.h b/src/xterm.h
index 16effc5c9ea..4a5ebc66370 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -53,14 +53,26 @@ typedef GtkWidget *xt_or_gtk_widget;
53#undef XSync 53#undef XSync
54#define XSync(d, b) do { gdk_window_process_all_updates (); \ 54#define XSync(d, b) do { gdk_window_process_all_updates (); \
55 XSync (d, b); } while (0) 55 XSync (d, b); } while (0)
56#endif /* USE_GTK */
57
58/* True iff GTK's version is at least I.J.K. */
59#ifndef GTK_CHECK_VERSION
60# ifdef USE_GTK
61# define GTK_CHECK_VERSION(i, j, k) \
62 ((i) \
63 < GTK_MAJOR_VERSION + ((j) \
64 < GTK_MINOR_VERSION + ((k) \
65 <= GTK_MICRO_VERSION)))
66# else
67# define GTK_CHECK_VERSION(i, j, k) 0
68# endif
69#endif
56 70
57/* The GtkTooltip API came in 2.12, but gtk-enable-tooltips in 2.14. */ 71/* The GtkTooltip API came in 2.12, but gtk-enable-tooltips in 2.14. */
58#if GTK_MAJOR_VERSION > 2 || GTK_MINOR_VERSION > 13 72#if GTK_CHECK_VERSION (2, 14, 0)
59#define USE_GTK_TOOLTIP 73#define USE_GTK_TOOLTIP
60#endif 74#endif
61 75
62#endif /* USE_GTK */
63
64 76
65/* Bookkeeping to distinguish X versions. */ 77/* Bookkeeping to distinguish X versions. */
66 78
@@ -346,7 +358,8 @@ struct x_display_info
346 Atom Xatom_net_wm_state, Xatom_net_wm_state_fullscreen, 358 Atom Xatom_net_wm_state, Xatom_net_wm_state_fullscreen,
347 Xatom_net_wm_state_maximized_horz, Xatom_net_wm_state_maximized_vert, 359 Xatom_net_wm_state_maximized_horz, Xatom_net_wm_state_maximized_vert,
348 Xatom_net_wm_state_sticky, Xatom_net_wm_state_hidden, 360 Xatom_net_wm_state_sticky, Xatom_net_wm_state_hidden,
349 Xatom_net_frame_extents; 361 Xatom_net_frame_extents,
362 Xatom_net_current_desktop, Xatom_net_workarea;
350 363
351 /* XSettings atoms and windows. */ 364 /* XSettings atoms and windows. */
352 Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr; 365 Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr;