diff options
| author | Eli Zaretskii | 2013-05-15 19:15:07 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2013-05-15 19:15:07 +0300 |
| commit | d14365f9411ab4b20db6c455aa9cf24ce6a0bcb1 (patch) | |
| tree | f547c3f203c903b118348061eb0fd2359c94d324 /src | |
| parent | f94b5742a3e9bc7114c6e2cd85a2371381cba4d3 (diff) | |
| parent | e3772e9833f971a450562350dc233bf00be7c5eb (diff) | |
| download | emacs-d14365f9411ab4b20db6c455aa9cf24ce6a0bcb1.tar.gz emacs-d14365f9411ab4b20db6c455aa9cf24ce6a0bcb1.zip | |
Merge from trunk, configury not fixed yet.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 230 | ||||
| -rw-r--r-- | src/Makefile.in | 17 | ||||
| -rw-r--r-- | src/buffer.c | 4 | ||||
| -rw-r--r-- | src/callint.c | 12 | ||||
| -rw-r--r-- | src/dispextern.h | 15 | ||||
| -rw-r--r-- | src/doc.c | 22 | ||||
| -rw-r--r-- | src/fileio.c | 107 | ||||
| -rw-r--r-- | src/filelock.c | 10 | ||||
| -rw-r--r-- | src/gtkutil.c | 9 | ||||
| -rw-r--r-- | src/image.c | 19 | ||||
| -rw-r--r-- | src/lread.c | 28 | ||||
| -rw-r--r-- | src/makefile.w32-in | 4 | ||||
| -rw-r--r-- | src/minibuf.c | 34 | ||||
| -rw-r--r-- | src/nsfns.m | 251 | ||||
| -rw-r--r-- | src/nsfont.m | 7 | ||||
| -rw-r--r-- | src/nsmenu.m | 8 | ||||
| -rw-r--r-- | src/regex.c | 387 | ||||
| -rw-r--r-- | src/unexelf.c | 204 | ||||
| -rw-r--r-- | src/w32fns.c | 25 | ||||
| -rw-r--r-- | src/xdisp.c | 71 | ||||
| -rw-r--r-- | src/xfns.c | 583 | ||||
| -rw-r--r-- | src/xterm.c | 4 | ||||
| -rw-r--r-- | src/xterm.h | 21 |
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 @@ | |||
| 1 | 2013-05-15 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * regex.c (regex_compile) [\=, \>, \<]: Don't forget to set laststart. | ||
| 4 | |||
| 5 | 2013-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 | |||
| 11 | 2013-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 | |||
| 16 | 2013-05-12 Paul Eggert <eggert@cs.ucla.edu> | ||
| 17 | |||
| 18 | * image.c (gif_load): Check that subimages fit (Bug#14345). | ||
| 19 | |||
| 20 | 2013-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 | |||
| 27 | 2013-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 | |||
| 38 | 2013-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 | |||
| 45 | 2013-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 | |||
| 51 | 2013-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 | |||
| 62 | 2013-05-08 Juanma Barranquero <lekktu@gmail.com> | ||
| 63 | |||
| 64 | * makefile.w32-in (ACL_H): New macro. | ||
| 65 | ($(BLD)/fileio.$(O)): Update dependencies. | ||
| 66 | |||
| 67 | 2013-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 | |||
| 86 | 2013-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 | |||
| 92 | 2013-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 | |||
| 97 | 2013-05-07 Glenn Morris <rgm@gnu.org> | ||
| 98 | |||
| 99 | * lread.c (readchar): Don't read from a dead buffer. (Bug#14280) | ||
| 100 | |||
| 101 | 2013-05-07 Jan Djärv <jan.h.d@swipnet.se> | ||
| 102 | |||
| 103 | * xfns.c: Move misplaced ifndef USE_GTK from previous checkin. | ||
| 104 | |||
| 105 | 2013-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 | |||
| 119 | 2013-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 | |||
| 144 | 2013-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 | |||
| 151 | 2013-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 | |||
| 194 | 2013-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 | |||
| 201 | 2013-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 | |||
| 206 | 2013-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 | |||
| 214 | 2013-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 | |||
| 221 | 2013-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 | |||
| 1 | 2013-05-01 David Reitter <david.reitter@gmail.com> | 230 | 2013-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 | ||
| 37 | 2013-04-26 Paul Eggert <eggert@cs.ucla.edu> | 266 | 2013-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@ | |||
| 137 | M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@ | 137 | M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@ |
| 138 | M17N_FLT_LIBS = @M17N_FLT_LIBS@ | 138 | M17N_FLT_LIBS = @M17N_FLT_LIBS@ |
| 139 | 139 | ||
| 140 | LIB_ACL=@LIB_ACL@ | ||
| 140 | LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@ | 141 | LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@ |
| 141 | LIB_EACCESS=@LIB_EACCESS@ | 142 | LIB_EACCESS=@LIB_EACCESS@ |
| 142 | LIB_FDATASYNC=@LIB_FDATASYNC@ | 143 | LIB_FDATASYNC=@LIB_FDATASYNC@ |
| @@ -232,6 +233,12 @@ IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@ | |||
| 232 | LIBXML2_LIBS = @LIBXML2_LIBS@ | 233 | LIBXML2_LIBS = @LIBXML2_LIBS@ |
| 233 | LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ | 234 | LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ |
| 234 | 235 | ||
| 236 | XRANDR_LIBS = @XRANDR_LIBS@ | ||
| 237 | XRANDR_CFLAGS = @XRANDR_CFLAGS@ | ||
| 238 | |||
| 239 | XINERAMA_LIBS = @XINERAMA_LIBS@ | ||
| 240 | XINERAMA_CFLAGS = @XINERAMA_CFLAGS@ | ||
| 241 | |||
| 235 | ## widget.o if USE_X_TOOLKIT, otherwise empty. | 242 | ## widget.o if USE_X_TOOLKIT, otherwise empty. |
| 236 | WIDGET_OBJ=@WIDGET_OBJ@ | 243 | WIDGET_OBJ=@WIDGET_OBJ@ |
| 237 | 244 | ||
| @@ -288,8 +295,6 @@ LIBSELINUX_LIBS = @LIBSELINUX_LIBS@ | |||
| 288 | LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@ | 295 | LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@ |
| 289 | LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@ | 296 | LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@ |
| 290 | 297 | ||
| 291 | LIBACL_LIBS = @LIBACL_LIBS@ | ||
| 292 | |||
| 293 | LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@ | 298 | LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@ |
| 294 | 299 | ||
| 295 | INTERVALS_H = dispextern.h intervals.h composite.h | 300 | INTERVALS_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. |
| 408 | LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ | 413 | LIBES = $(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 | ||
| 419 | all: emacs$(EXEEXT) $(OTHER_FILES) | 424 | all: 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. |
| 5504 | NOTE: This controls the display width of a TAB character, and not | ||
| 5505 | the size of an indentation step. | ||
| 5504 | This is the same as (default-value 'tab-width). */); | 5506 | This 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. |
| 5697 | NOTE: This controls the display width of a TAB character, and not | ||
| 5698 | the size of an indentation step. | ||
| 5695 | This should be an integer greater than zero. */); | 5699 | This 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 |
| @@ -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 | |||
| 6069 | file is usually more useful if it contains the deleted text. */); | 6037 | file 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'. |
| 6074 | This variable affects calls to `write-region' as well as save commands. | 6058 | This variable affects calls to `write-region' as well as save commands. |
| 6075 | A non-nil value may result in data loss! */); | 6059 | Setting this to nil may avoid data loss if the system loses power or |
| 6076 | write_region_inhibit_fsync = 0; | 6060 | the 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 | ||
| 381 | static void | ||
| 382 | skip_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 = .. | |||
| 388 | GNU_LIB = $(EMACS_ROOT)/lib | 388 | GNU_LIB = $(EMACS_ROOT)/lib |
| 389 | NT_INC = $(EMACS_ROOT)/nt/inc | 389 | NT_INC = $(EMACS_ROOT)/nt/inc |
| 390 | 390 | ||
| 391 | ACL_H = $(GNU_LIB)/acl.h \ | ||
| 392 | $(NT_INC)/sys/stat.h \ | ||
| 393 | $(NT_INC)/stdbool.h | ||
| 391 | SYSTIME_H = $(SRC)/systime.h \ | 394 | SYSTIME_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 | ||
| 989 | DEFUN ("read-minibuffer", Fread_minibuffer, Sread_minibuffer, 1, 2, 0, | ||
| 990 | doc: /* Return a Lisp object read using the minibuffer, unevaluated. | ||
| 991 | Prompt with PROMPT. If non-nil, optional second arg INITIAL-CONTENTS | ||
| 992 | is a string to insert in the minibuffer before reading. | ||
| 993 | \(INITIAL-CONTENTS can also be a cons of a string and an integer. | ||
| 994 | Such 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 | |||
| 1003 | DEFUN ("eval-minibuffer", Feval_minibuffer, Seval_minibuffer, 1, 2, 0, | ||
| 1004 | doc: /* Return value of Lisp expression read using the minibuffer. | ||
| 1005 | Prompt with PROMPT. If non-nil, optional second arg INITIAL-CONTENTS | ||
| 1006 | is a string to insert in the minibuffer before reading. | ||
| 1007 | \(INITIAL-CONTENTS can also be a cons of a string and an integer. | ||
| 1008 | Such 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 | ||
| 1019 | DEFUN ("read-string", Fread_string, Sread_string, 1, 5, 0, | 991 | DEFUN ("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 |
| 48 | int fns_trace_num = 1; | 52 | int 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; | |||
| 101 | static ptrdiff_t image_cache_refcount; | 105 | static ptrdiff_t image_cache_refcount; |
| 102 | #endif | 106 | #endif |
| 103 | 107 | ||
| 108 | static 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 | ||
| 2330 | struct MonitorInfo { | ||
| 2331 | XRectangle geom, work; | ||
| 2332 | int mm_width, mm_height; | ||
| 2333 | char *name; | ||
| 2334 | }; | ||
| 2324 | 2335 | ||
| 2325 | DEFUN ("display-usable-bounds", Fns_display_usable_bounds, | 2336 | static void |
| 2326 | Sns_display_usable_bounds, 0, 1, 0, | 2337 | free_monitors (struct MonitorInfo *monitors, int n_monitors) |
| 2327 | doc: /* Return the bounds of the usable part of the screen. | 2338 | { |
| 2328 | The return value is a list of integers (LEFT TOP WIDTH HEIGHT), which | 2339 | int i; |
| 2329 | are the boundaries of the usable part of the screen, excluding areas | 2340 | for (i = 0; i < n_monitors; ++i) |
| 2330 | reserved for the Mac menu, dock, and so forth. | 2341 | xfree (monitors[i].name); |
| 2342 | xfree (monitors); | ||
| 2343 | } | ||
| 2331 | 2344 | ||
| 2332 | The screen queried corresponds to DISPLAY, which should be either a | 2345 | #ifdef NS_IMPL_COCOA |
| 2333 | frame, 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. |
| 2334 | that stands for the selected frame's display. */) | 2347 | Caller must free return value. |
| 2335 | (Lisp_Object display) | 2348 | */ |
| 2349 | |||
| 2350 | char * | ||
| 2351 | ns_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 | |||
| 2372 | static Lisp_Object | ||
| 2373 | ns_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 | |||
| 2443 | DEFUN ("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 | |||
| 2449 | The optional argument TERMINAL specifies which display to ask about. | ||
| 2450 | TERMINAL should be a terminal object, a frame or a display name (a string). | ||
| 2451 | If omitted or nil, that stands for the selected frame's display. | ||
| 2452 | |||
| 2453 | In addition to the standard attribute keys listed in | ||
| 2454 | `display-monitor-attributes-list', the following keys are contained in | ||
| 2455 | the attributes: | ||
| 2456 | |||
| 2457 | source -- String describing the source from which multi-monitor | ||
| 2458 | information is obtained, \"NS\" is always the source." | ||
| 2459 | |||
| 2460 | Internal 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 | */ |
| 2551 | static BOOL | 2743 | static BOOL |
| 2552 | handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent) | 2744 | handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent) |
| @@ -2729,6 +2921,11 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent) | |||
| 2729 | void | 2921 | void |
| 2730 | syms_of_nsfns (void) | 2922 | syms_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 | 715 | static int |
| 719 | static void | 716 | extract_number (re_char *source) |
| 720 | extract_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 | 727 | static int |
| 744 | static void | 728 | extract_number_and_incr (re_char **source) |
| 745 | extract_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) | |||
| 861 | static int debug = -100000; | 837 | static 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 | ||
| 876 | void | 850 | static void |
| 877 | print_fastmap (fastmap) | 851 | print_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 | ||
| 908 | void | 881 | static void |
| 909 | print_partial_compiled_pattern (start, end) | 882 | print_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 | ||
| 1158 | void | 1136 | static void |
| 1159 | print_compiled_pattern (bufp) | 1137 | print_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 | ||
| 1186 | void | 1163 | static void |
| 1187 | print_double_string (where, string1, size1, string2, size2) | 1164 | print_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 | |||
| 1469 | while (REMAINING_AVAIL_SLOTS <= space) { \ | 1444 | while (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) \ |
| 1478 | do { \ | 1453 | do { \ |
| 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 | ||
| 391 | extern void fatal (const char *msgid, ...); | 391 | extern _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> | ||
| 529 | verify ((! 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 | ||
| 564 | static void * | ||
| 565 | entry_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) | ||
| 560 | typedef unsigned char byte; | 579 | typedef 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; | |||
| 564 | static ElfW (Addr) | 583 | static ElfW (Addr) |
| 565 | round_up (ElfW (Addr) x, ElfW (Addr) y) | 584 | round_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 | ||
| 580 | static int | 599 | static ptrdiff_t |
| 581 | find_section (const char *name, const char *section_names, const char *file_name, | 600 | find_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 | |||
| 616 | void | 630 | void |
| 617 | unexec (const char *new_name, const char *old_name) | 631 | unexec (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); | |||
| 794 | static void mark_window_display_accurate_1 (struct window *, int); | 794 | static void mark_window_display_accurate_1 (struct window *, int); |
| 795 | static int single_display_spec_string_p (Lisp_Object, Lisp_Object); | 795 | static int single_display_spec_string_p (Lisp_Object, Lisp_Object); |
| 796 | static int display_prop_string_p (Lisp_Object, Lisp_Object); | 796 | static int display_prop_string_p (Lisp_Object, Lisp_Object); |
| 797 | static int row_for_charpos_p (struct glyph_row *, ptrdiff_t); | ||
| 797 | static int cursor_row_p (struct glyph_row *); | 798 | static int cursor_row_p (struct glyph_row *); |
| 798 | static int redisplay_mode_lines (Lisp_Object, int); | 799 | static int redisplay_mode_lines (Lisp_Object, int); |
| 799 | static char *decode_mode_spec_coding (Lisp_Object, char *, int); | 800 | static 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 | ||
| 18718 | static int | 18732 | static int |
| 18719 | cursor_row_p (struct glyph_row *row) | 18733 | row_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 | |||
| 18821 | static int | ||
| 18822 | cursor_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; | |||
| 126 | static Lisp_Object Qsuppress_icon; | 133 | static Lisp_Object Qsuppress_icon; |
| 127 | static Lisp_Object Qundefined_color; | 134 | static Lisp_Object Qundefined_color; |
| 128 | static Lisp_Object Qcompound_text, Qcancel_timer; | 135 | static Lisp_Object Qcompound_text, Qcancel_timer; |
| 136 | static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource; | ||
| 129 | Lisp_Object Qfont_param; | 137 | Lisp_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) | ||
| 3808 | static bool | ||
| 3809 | x_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 | |||
| 3869 | struct MonitorInfo { | ||
| 3870 | XRectangle geom, work; | ||
| 3871 | int mm_width, mm_height; | ||
| 3872 | char *name; | ||
| 3873 | }; | ||
| 3874 | |||
| 3875 | #if defined HAVE_XINERAMA || defined HAVE_XRANDR | ||
| 3876 | static void | ||
| 3877 | free_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. */ | ||
| 3888 | static int | ||
| 3889 | x_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 | |||
| 3950 | static Lisp_Object | ||
| 3951 | x_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 | |||
| 4011 | static Lisp_Object | ||
| 4012 | x_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 | ||
| 4036 | static Lisp_Object | ||
| 4037 | x_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 | ||
| 4095 | static Lisp_Object | ||
| 4096 | x_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 | |||
| 4189 | static Lisp_Object | ||
| 4190 | x_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 | |||
| 4229 | DEFUN ("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 | |||
| 4234 | The optional argument TERMINAL specifies which display to ask about. | ||
| 4235 | TERMINAL should be a terminal object, a frame or a display name (a string). | ||
| 4236 | If omitted or nil, that stands for the selected frame's display. | ||
| 4237 | |||
| 4238 | In addition to the standard attribute keys listed in | ||
| 4239 | `display-monitor-attributes-list', the following keys are contained in | ||
| 4240 | the 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 | |||
| 4246 | Internal 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 | ||
| 3795 | int | 4372 | int |
| 3796 | x_pixel_width (register struct frame *f) | 4373 | x_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; |