aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Albinus2017-06-05 13:00:07 +0200
committerMichael Albinus2017-06-05 13:00:07 +0200
commit9f496c591d457b511a42c0f63e0d2d923cda0247 (patch)
tree86b550b9b3a8c1b5cb33bfdca82e470ab211bfac /src
parent751d5920bed1a3af01fd5a31ce4eb7d8b6994151 (diff)
parent13e9493ea36df04e2c6b69e9b316d40c072ee88b (diff)
downloademacs-9f496c591d457b511a42c0f63e0d2d923cda0247.tar.gz
emacs-9f496c591d457b511a42c0f63e0d2d923cda0247.zip
Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs
Diffstat (limited to 'src')
-rw-r--r--src/data.c10
-rw-r--r--src/dynlib.c34
-rw-r--r--src/dynlib.h16
-rw-r--r--src/editfns.c154
-rw-r--r--src/emacs-module.c162
-rw-r--r--src/emacs-module.h3
-rw-r--r--src/eval.c7
-rw-r--r--src/lisp.h16
-rw-r--r--src/print.c30
9 files changed, 226 insertions, 206 deletions
diff --git a/src/data.c b/src/data.c
index 25859105ee0..e4e55290e62 100644
--- a/src/data.c
+++ b/src/data.c
@@ -700,12 +700,10 @@ global value outside of any lexical scope. */)
700 return (EQ (valcontents, Qunbound) ? Qnil : Qt); 700 return (EQ (valcontents, Qunbound) ? Qnil : Qt);
701} 701}
702 702
703/* FIXME: It has been previously suggested to make this function an 703/* It has been previously suggested to make this function an alias for
704 alias for symbol-function, but upon discussion at Bug#23957, 704 symbol-function, but upon discussion at Bug#23957, there is a risk
705 there is a risk breaking backward compatibility, as some users of 705 breaking backward compatibility, as some users of fboundp may
706 fboundp may expect `t' in particular, rather than any true 706 expect `t' in particular, rather than any true value. */
707 value. An alias is still welcome so long as the compatibility
708 issues are addressed. */
709DEFUN ("fboundp", Ffboundp, Sfboundp, 1, 1, 0, 707DEFUN ("fboundp", Ffboundp, Sfboundp, 1, 1, 0,
710 doc: /* Return t if SYMBOL's function definition is not void. */) 708 doc: /* Return t if SYMBOL's function definition is not void. */)
711 (register Lisp_Object symbol) 709 (register Lisp_Object symbol)
diff --git a/src/dynlib.c b/src/dynlib.c
index 95619236d43..79e98b0f288 100644
--- a/src/dynlib.c
+++ b/src/dynlib.c
@@ -28,6 +28,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28 28
29#include "dynlib.h" 29#include "dynlib.h"
30 30
31#include <stddef.h>
32
31#ifdef WINDOWSNT 33#ifdef WINDOWSNT
32 34
33/* MS-Windows systems. */ 35/* MS-Windows systems. */
@@ -120,7 +122,7 @@ dynlib_sym (dynlib_handle_ptr h, const char *sym)
120 return (void *)sym_addr; 122 return (void *)sym_addr;
121} 123}
122 124
123bool 125void
124dynlib_addr (void *addr, const char **fname, const char **symname) 126dynlib_addr (void *addr, const char **fname, const char **symname)
125{ 127{
126 static char dll_filename[MAX_UTF8_PATH]; 128 static char dll_filename[MAX_UTF8_PATH];
@@ -128,7 +130,6 @@ dynlib_addr (void *addr, const char **fname, const char **symname)
128 static GetModuleHandleExA_Proc s_pfn_Get_Module_HandleExA = NULL; 130 static GetModuleHandleExA_Proc s_pfn_Get_Module_HandleExA = NULL;
129 char *dll_fn = NULL; 131 char *dll_fn = NULL;
130 HMODULE hm_kernel32 = NULL; 132 HMODULE hm_kernel32 = NULL;
131 bool result = false;
132 HMODULE hm_dll = NULL; 133 HMODULE hm_dll = NULL;
133 wchar_t mfn_w[MAX_PATH]; 134 wchar_t mfn_w[MAX_PATH];
134 char mfn_a[MAX_PATH]; 135 char mfn_a[MAX_PATH];
@@ -206,23 +207,18 @@ dynlib_addr (void *addr, const char **fname, const char **symname)
206 dynlib_last_err = GetLastError (); 207 dynlib_last_err = GetLastError ();
207 } 208 }
208 if (dll_fn) 209 if (dll_fn)
209 { 210 dostounix_filename (dll_fn);
210 dostounix_filename (dll_fn);
211 /* We cannot easily produce the function name, since
212 typically all of the module functions will be unexported,
213 and probably even static, which means the symbols can be
214 obtained only if we link against libbfd (and the DLL can
215 be stripped anyway). So we just show the address and the
216 file name; they can use that with addr2line or GDB to
217 recover the symbolic name. */
218 sprintf (addr_str, "at 0x%x", (DWORD_PTR)addr);
219 *symname = addr_str;
220 result = true;
221 }
222 } 211 }
223 212
224 *fname = dll_fn; 213 *fname = dll_fn;
225 return result; 214
215 /* We cannot easily produce the function name, since typically all
216 of the module functions will be unexported, and probably even
217 static, which means the symbols can be obtained only if we link
218 against libbfd (and the DLL can be stripped anyway). So we just
219 show the address and the file name; they can use that with
220 addr2line or GDB to recover the symbolic name. */
221 *symname = NULL;
226} 222}
227 223
228const char * 224const char *
@@ -283,19 +279,19 @@ dynlib_sym (dynlib_handle_ptr h, const char *sym)
283 return dlsym (h, sym); 279 return dlsym (h, sym);
284} 280}
285 281
286bool 282void
287dynlib_addr (void *ptr, const char **path, const char **sym) 283dynlib_addr (void *ptr, const char **path, const char **sym)
288{ 284{
285 *path = NULL;
286 *sym = NULL;
289#ifdef HAVE_DLADDR 287#ifdef HAVE_DLADDR
290 Dl_info info; 288 Dl_info info;
291 if (dladdr (ptr, &info) && info.dli_fname && info.dli_sname) 289 if (dladdr (ptr, &info) && info.dli_fname && info.dli_sname)
292 { 290 {
293 *path = info.dli_fname; 291 *path = info.dli_fname;
294 *sym = info.dli_sname; 292 *sym = info.dli_sname;
295 return true;
296 } 293 }
297#endif 294#endif
298 return false;
299} 295}
300 296
301const char * 297const char *
diff --git a/src/dynlib.h b/src/dynlib.h
index 5ccec11bc79..1d53b8e5b2f 100644
--- a/src/dynlib.h
+++ b/src/dynlib.h
@@ -24,11 +24,17 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24 24
25typedef void *dynlib_handle_ptr; 25typedef void *dynlib_handle_ptr;
26dynlib_handle_ptr dynlib_open (const char *path); 26dynlib_handle_ptr dynlib_open (const char *path);
27void *dynlib_sym (dynlib_handle_ptr h, const char *sym);
28typedef struct dynlib_function_ptr_nonce *(*dynlib_function_ptr) (void);
29dynlib_function_ptr dynlib_func (dynlib_handle_ptr h, const char *sym);
30bool dynlib_addr (void *ptr, const char **path, const char **sym);
31const char *dynlib_error (void);
32int dynlib_close (dynlib_handle_ptr h); 27int dynlib_close (dynlib_handle_ptr h);
28const char *dynlib_error (void);
29
30ATTRIBUTE_MAY_ALIAS void *dynlib_sym (dynlib_handle_ptr h, const char *sym);
31
32typedef struct dynlib_function_ptr_nonce *(ATTRIBUTE_MAY_ALIAS *dynlib_function_ptr) (void);
33dynlib_function_ptr dynlib_func (dynlib_handle_ptr h, const char *sym);
34
35/* Sets *FILE to the file name from which PTR was loaded, and *SYM to
36 its symbol name. If the file or symbol name could not be
37 determined, set the corresponding argument to NULL. */
38void dynlib_addr (void *ptr, const char **file, const char **sym);
33 39
34#endif /* DYNLIB_H */ 40#endif /* DYNLIB_H */
diff --git a/src/editfns.c b/src/editfns.c
index 56aa8ce1a72..43b17f9f116 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -3891,8 +3891,8 @@ the next available argument, or the argument explicitly specified:
3891The argument used for %d, %o, %x, %e, %f, %g or %c must be a number. 3891The argument used for %d, %o, %x, %e, %f, %g or %c must be a number.
3892Use %% to put a single % into the output. 3892Use %% to put a single % into the output.
3893 3893
3894A %-sequence may contain optional field number, flag, width, and 3894A %-sequence other than %% may contain optional field number, flag,
3895precision specifiers, as follows: 3895width, and precision specifiers, as follows:
3896 3896
3897 %<field><flags><width><precision>character 3897 %<field><flags><width><precision>character
3898 3898
@@ -3901,10 +3901,9 @@ where field is [0-9]+ followed by a literal dollar "$", flags is
3901followed by [0-9]+. 3901followed by [0-9]+.
3902 3902
3903If a %-sequence is numbered with a field with positive value N, the 3903If a %-sequence is numbered with a field with positive value N, the
3904Nth argument is substituted instead of the next one. A field number 3904Nth argument is substituted instead of the next one. A format can
3905should differ from the other field numbers in the same format. A 3905contain either numbered or unnumbered %-sequences but not both, except
3906format can contain either numbered or unnumbered %-sequences but not 3906that %% can be mixed with numbered %-sequences.
3907both, except that %% can be mixed with numbered %-sequences.
3908 3907
3909The + flag character inserts a + before any positive number, while a 3908The + flag character inserts a + before any positive number, while a
3910space inserts a space before any positive number; these flags only 3909space inserts a space before any positive number; these flags only
@@ -3980,49 +3979,40 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
3980 bool arg_intervals = false; 3979 bool arg_intervals = false;
3981 USE_SAFE_ALLOCA; 3980 USE_SAFE_ALLOCA;
3982 3981
3983 /* Each element records, for one field, 3982 /* Information recorded for each format spec. */
3984 the corresponding argument,
3985 the start and end bytepos in the output string,
3986 whether the argument has been converted to string (e.g., due to "%S"),
3987 and whether the argument is a string with intervals. */
3988 struct info 3983 struct info
3989 { 3984 {
3985 /* The corresponding argument, converted to string if conversion
3986 was needed. */
3990 Lisp_Object argument; 3987 Lisp_Object argument;
3988
3989 /* The start and end bytepos in the output string. */
3991 ptrdiff_t start, end; 3990 ptrdiff_t start, end;
3992 bool_bf converted_to_string : 1; 3991
3992 /* Whether the argument is a string with intervals. */
3993 bool_bf intervals : 1; 3993 bool_bf intervals : 1;
3994 } *info; 3994 } *info;
3995 3995
3996 CHECK_STRING (args[0]); 3996 CHECK_STRING (args[0]);
3997 char *format_start = SSDATA (args[0]); 3997 char *format_start = SSDATA (args[0]);
3998 bool multibyte_format = STRING_MULTIBYTE (args[0]);
3998 ptrdiff_t formatlen = SBYTES (args[0]); 3999 ptrdiff_t formatlen = SBYTES (args[0]);
3999 4000
4000 /* The number of percent characters is a safe upper bound for the 4001 /* Upper bound on number of format specs. Each uses at least 2 chars. */
4001 number of format fields. */ 4002 ptrdiff_t nspec_bound = SCHARS (args[0]) >> 1;
4002 ptrdiff_t num_percent = 0;
4003 for (ptrdiff_t i = 0; i < formatlen; ++i)
4004 if (format_start[i] == '%')
4005 ++num_percent;
4006 4003
4007 /* Allocate the info and discarded tables. */ 4004 /* Allocate the info and discarded tables. */
4008 ptrdiff_t alloca_size; 4005 ptrdiff_t alloca_size;
4009 if (INT_MULTIPLY_WRAPV (num_percent, sizeof *info, &alloca_size) 4006 if (INT_MULTIPLY_WRAPV (nspec_bound, sizeof *info, &alloca_size)
4010 || INT_ADD_WRAPV (sizeof *info, alloca_size, &alloca_size)
4011 || INT_ADD_WRAPV (formatlen, alloca_size, &alloca_size) 4007 || INT_ADD_WRAPV (formatlen, alloca_size, &alloca_size)
4012 || SIZE_MAX < alloca_size) 4008 || SIZE_MAX < alloca_size)
4013 memory_full (SIZE_MAX); 4009 memory_full (SIZE_MAX);
4014 /* info[0] is unused. Unused elements have -1 for start. */
4015 info = SAFE_ALLOCA (alloca_size); 4010 info = SAFE_ALLOCA (alloca_size);
4016 memset (info, 0, alloca_size);
4017 for (ptrdiff_t i = 0; i < num_percent + 1; i++)
4018 {
4019 info[i].argument = Qunbound;
4020 info[i].start = -1;
4021 }
4022 /* discarded[I] is 1 if byte I of the format 4011 /* discarded[I] is 1 if byte I of the format
4023 string was not copied into the output. 4012 string was not copied into the output.
4024 It is 2 if byte I was not the first byte of its character. */ 4013 It is 2 if byte I was not the first byte of its character. */
4025 char *discarded = (char *) &info[num_percent + 1]; 4014 char *discarded = (char *) &info[nspec_bound];
4015 memset (discarded, 0, formatlen);
4026 4016
4027 /* Try to determine whether the result should be multibyte. 4017 /* Try to determine whether the result should be multibyte.
4028 This is not always right; sometimes the result needs to be multibyte 4018 This is not always right; sometimes the result needs to be multibyte
@@ -4030,8 +4020,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4030 or because a grave accent or apostrophe is requoted, 4020 or because a grave accent or apostrophe is requoted,
4031 and in that case, we won't know it here. */ 4021 and in that case, we won't know it here. */
4032 4022
4033 /* True if the format is multibyte. */
4034 bool multibyte_format = STRING_MULTIBYTE (args[0]);
4035 /* True if the output should be a multibyte string, 4023 /* True if the output should be a multibyte string,
4036 which is true if any of the inputs is one. */ 4024 which is true if any of the inputs is one. */
4037 bool multibyte = multibyte_format; 4025 bool multibyte = multibyte_format;
@@ -4042,6 +4030,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4042 int quoting_style = message ? text_quoting_style () : -1; 4030 int quoting_style = message ? text_quoting_style () : -1;
4043 4031
4044 ptrdiff_t ispec; 4032 ptrdiff_t ispec;
4033 ptrdiff_t nspec = 0;
4045 4034
4046 /* If we start out planning a unibyte result, 4035 /* If we start out planning a unibyte result,
4047 then discover it has to be multibyte, we jump back to retry. */ 4036 then discover it has to be multibyte, we jump back to retry. */
@@ -4155,11 +4144,14 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4155 if (! (n < nargs)) 4144 if (! (n < nargs))
4156 error ("Not enough arguments for format string"); 4145 error ("Not enough arguments for format string");
4157 4146
4158 eassert (ispec < num_percent); 4147 struct info *spec = &info[ispec++];
4159 ++ispec; 4148 if (nspec < ispec)
4160 4149 {
4161 if (EQ (info[ispec].argument, Qunbound)) 4150 spec->argument = args[n];
4162 info[ispec].argument = args[n]; 4151 spec->intervals = false;
4152 nspec = ispec;
4153 }
4154 Lisp_Object arg = spec->argument;
4163 4155
4164 /* For 'S', prin1 the argument, and then treat like 's'. 4156 /* For 'S', prin1 the argument, and then treat like 's'.
4165 For 's', princ any argument that is not a string or 4157 For 's', princ any argument that is not a string or
@@ -4167,16 +4159,13 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4167 happen after retrying. */ 4159 happen after retrying. */
4168 if ((conversion == 'S' 4160 if ((conversion == 'S'
4169 || (conversion == 's' 4161 || (conversion == 's'
4170 && ! STRINGP (info[ispec].argument) 4162 && ! STRINGP (arg) && ! SYMBOLP (arg))))
4171 && ! SYMBOLP (info[ispec].argument))))
4172 { 4163 {
4173 if (! info[ispec].converted_to_string) 4164 if (EQ (arg, args[n]))
4174 { 4165 {
4175 Lisp_Object noescape = conversion == 'S' ? Qnil : Qt; 4166 Lisp_Object noescape = conversion == 'S' ? Qnil : Qt;
4176 info[ispec].argument = 4167 spec->argument = arg = Fprin1_to_string (arg, noescape);
4177 Fprin1_to_string (info[ispec].argument, noescape); 4168 if (STRING_MULTIBYTE (arg) && ! multibyte)
4178 info[ispec].converted_to_string = true;
4179 if (STRING_MULTIBYTE (info[ispec].argument) && ! multibyte)
4180 { 4169 {
4181 multibyte = true; 4170 multibyte = true;
4182 goto retry; 4171 goto retry;
@@ -4186,29 +4175,25 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4186 } 4175 }
4187 else if (conversion == 'c') 4176 else if (conversion == 'c')
4188 { 4177 {
4189 if (INTEGERP (info[ispec].argument) 4178 if (INTEGERP (arg) && ! ASCII_CHAR_P (XINT (arg)))
4190 && ! ASCII_CHAR_P (XINT (info[ispec].argument)))
4191 { 4179 {
4192 if (!multibyte) 4180 if (!multibyte)
4193 { 4181 {
4194 multibyte = true; 4182 multibyte = true;
4195 goto retry; 4183 goto retry;
4196 } 4184 }
4197 info[ispec].argument = 4185 spec->argument = arg = Fchar_to_string (arg);
4198 Fchar_to_string (info[ispec].argument);
4199 info[ispec].converted_to_string = true;
4200 } 4186 }
4201 4187
4202 if (info[ispec].converted_to_string) 4188 if (!EQ (arg, args[n]))
4203 conversion = 's'; 4189 conversion = 's';
4204 zero_flag = false; 4190 zero_flag = false;
4205 } 4191 }
4206 4192
4207 if (SYMBOLP (info[ispec].argument)) 4193 if (SYMBOLP (arg))
4208 { 4194 {
4209 info[ispec].argument = 4195 spec->argument = arg = SYMBOL_NAME (arg);
4210 SYMBOL_NAME (info[ispec].argument); 4196 if (STRING_MULTIBYTE (arg) && ! multibyte)
4211 if (STRING_MULTIBYTE (info[ispec].argument) && ! multibyte)
4212 { 4197 {
4213 multibyte = true; 4198 multibyte = true;
4214 goto retry; 4199 goto retry;
@@ -4239,12 +4224,11 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4239 else 4224 else
4240 { 4225 {
4241 ptrdiff_t nch, nby; 4226 ptrdiff_t nch, nby;
4242 width = lisp_string_width (info[ispec].argument, 4227 width = lisp_string_width (arg, prec, &nch, &nby);
4243 prec, &nch, &nby);
4244 if (prec < 0) 4228 if (prec < 0)
4245 { 4229 {
4246 nchars_string = SCHARS (info[ispec].argument); 4230 nchars_string = SCHARS (arg);
4247 nbytes = SBYTES (info[ispec].argument); 4231 nbytes = SBYTES (arg);
4248 } 4232 }
4249 else 4233 else
4250 { 4234 {
@@ -4254,11 +4238,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4254 } 4238 }
4255 4239
4256 convbytes = nbytes; 4240 convbytes = nbytes;
4257 if (convbytes && multibyte && 4241 if (convbytes && multibyte && ! STRING_MULTIBYTE (arg))
4258 ! STRING_MULTIBYTE (info[ispec].argument)) 4242 convbytes = count_size_as_multibyte (SDATA (arg), nbytes);
4259 convbytes =
4260 count_size_as_multibyte (SDATA (info[ispec].argument),
4261 nbytes);
4262 4243
4263 ptrdiff_t padding 4244 ptrdiff_t padding
4264 = width < field_width ? field_width - width : 0; 4245 = width < field_width ? field_width - width : 0;
@@ -4274,20 +4255,18 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4274 p += padding; 4255 p += padding;
4275 nchars += padding; 4256 nchars += padding;
4276 } 4257 }
4277 info[ispec].start = nchars; 4258 spec->start = nchars;
4278 4259
4279 if (p > buf 4260 if (p > buf
4280 && multibyte 4261 && multibyte
4281 && !ASCII_CHAR_P (*((unsigned char *) p - 1)) 4262 && !ASCII_CHAR_P (*((unsigned char *) p - 1))
4282 && STRING_MULTIBYTE (info[ispec].argument) 4263 && STRING_MULTIBYTE (arg)
4283 && !CHAR_HEAD_P (SREF (info[ispec].argument, 0))) 4264 && !CHAR_HEAD_P (SREF (arg, 0)))
4284 maybe_combine_byte = true; 4265 maybe_combine_byte = true;
4285 4266
4286 p += copy_text (SDATA (info[ispec].argument), 4267 p += copy_text (SDATA (arg), (unsigned char *) p,
4287 (unsigned char *) p,
4288 nbytes, 4268 nbytes,
4289 STRING_MULTIBYTE (info[ispec].argument), 4269 STRING_MULTIBYTE (arg), multibyte);
4290 multibyte);
4291 4270
4292 nchars += nchars_string; 4271 nchars += nchars_string;
4293 4272
@@ -4297,12 +4276,12 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4297 p += padding; 4276 p += padding;
4298 nchars += padding; 4277 nchars += padding;
4299 } 4278 }
4300 info[ispec].end = nchars; 4279 spec->end = nchars;
4301 4280
4302 /* If this argument has text properties, record where 4281 /* If this argument has text properties, record where
4303 in the result string it appears. */ 4282 in the result string it appears. */
4304 if (string_intervals (info[ispec].argument)) 4283 if (string_intervals (arg))
4305 info[ispec].intervals = arg_intervals = true; 4284 spec->intervals = arg_intervals = true;
4306 4285
4307 continue; 4286 continue;
4308 } 4287 }
@@ -4313,8 +4292,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4313 || conversion == 'X')) 4292 || conversion == 'X'))
4314 error ("Invalid format operation %%%c", 4293 error ("Invalid format operation %%%c",
4315 STRING_CHAR ((unsigned char *) format - 1)); 4294 STRING_CHAR ((unsigned char *) format - 1));
4316 else if (! (INTEGERP (info[ispec].argument) 4295 else if (! (INTEGERP (arg) || (FLOATP (arg) && conversion != 'c')))
4317 || (FLOATP (info[ispec].argument) && conversion != 'c')))
4318 error ("Format specifier doesn't match argument type"); 4296 error ("Format specifier doesn't match argument type");
4319 else 4297 else
4320 { 4298 {
@@ -4376,7 +4354,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4376 if (INT_AS_LDBL) 4354 if (INT_AS_LDBL)
4377 { 4355 {
4378 *f = 'L'; 4356 *f = 'L';
4379 f += INTEGERP (info[ispec].argument); 4357 f += INTEGERP (arg);
4380 } 4358 }
4381 } 4359 }
4382 else if (conversion != 'c') 4360 else if (conversion != 'c')
@@ -4408,22 +4386,22 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4408 ptrdiff_t sprintf_bytes; 4386 ptrdiff_t sprintf_bytes;
4409 if (float_conversion) 4387 if (float_conversion)
4410 { 4388 {
4411 if (INT_AS_LDBL && INTEGERP (info[ispec].argument)) 4389 if (INT_AS_LDBL && INTEGERP (arg))
4412 { 4390 {
4413 /* Although long double may have a rounding error if 4391 /* Although long double may have a rounding error if
4414 DIG_BITS_LBOUND * LDBL_MANT_DIG < FIXNUM_BITS - 1, 4392 DIG_BITS_LBOUND * LDBL_MANT_DIG < FIXNUM_BITS - 1,
4415 it is more accurate than plain 'double'. */ 4393 it is more accurate than plain 'double'. */
4416 long double x = XINT (info[ispec].argument); 4394 long double x = XINT (arg);
4417 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x); 4395 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
4418 } 4396 }
4419 else 4397 else
4420 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, 4398 sprintf_bytes = sprintf (sprintf_buf, convspec, prec,
4421 XFLOATINT (info[ispec].argument)); 4399 XFLOATINT (arg));
4422 } 4400 }
4423 else if (conversion == 'c') 4401 else if (conversion == 'c')
4424 { 4402 {
4425 /* Don't use sprintf here, as it might mishandle prec. */ 4403 /* Don't use sprintf here, as it might mishandle prec. */
4426 sprintf_buf[0] = XINT (info[ispec].argument); 4404 sprintf_buf[0] = XINT (arg);
4427 sprintf_bytes = prec != 0; 4405 sprintf_bytes = prec != 0;
4428 } 4406 }
4429 else if (conversion == 'd' || conversion == 'i') 4407 else if (conversion == 'd' || conversion == 'i')
@@ -4432,11 +4410,11 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4432 instead so it also works for values outside 4410 instead so it also works for values outside
4433 the integer range. */ 4411 the integer range. */
4434 printmax_t x; 4412 printmax_t x;
4435 if (INTEGERP (info[ispec].argument)) 4413 if (INTEGERP (arg))
4436 x = XINT (info[ispec].argument); 4414 x = XINT (arg);
4437 else 4415 else
4438 { 4416 {
4439 double d = XFLOAT_DATA (info[ispec].argument); 4417 double d = XFLOAT_DATA (arg);
4440 if (d < 0) 4418 if (d < 0)
4441 { 4419 {
4442 x = TYPE_MINIMUM (printmax_t); 4420 x = TYPE_MINIMUM (printmax_t);
@@ -4456,11 +4434,11 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4456 { 4434 {
4457 /* Don't sign-extend for octal or hex printing. */ 4435 /* Don't sign-extend for octal or hex printing. */
4458 uprintmax_t x; 4436 uprintmax_t x;
4459 if (INTEGERP (info[ispec].argument)) 4437 if (INTEGERP (arg))
4460 x = XUINT (info[ispec].argument); 4438 x = XUINT (arg);
4461 else 4439 else
4462 { 4440 {
4463 double d = XFLOAT_DATA (info[ispec].argument); 4441 double d = XFLOAT_DATA (arg);
4464 if (d < 0) 4442 if (d < 0)
4465 x = 0; 4443 x = 0;
4466 else 4444 else
@@ -4541,7 +4519,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4541 exponent_bytes = src + sprintf_bytes - e; 4519 exponent_bytes = src + sprintf_bytes - e;
4542 } 4520 }
4543 4521
4544 info[ispec].start = nchars; 4522 spec->start = nchars;
4545 if (! minus_flag) 4523 if (! minus_flag)
4546 { 4524 {
4547 memset (p, ' ', padding); 4525 memset (p, ' ', padding);
@@ -4572,7 +4550,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4572 p += padding; 4550 p += padding;
4573 nchars += padding; 4551 nchars += padding;
4574 } 4552 }
4575 info[ispec].end = nchars; 4553 spec->end = nchars;
4576 4554
4577 continue; 4555 continue;
4578 } 4556 }
@@ -4681,7 +4659,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4681 if (CONSP (props)) 4659 if (CONSP (props))
4682 { 4660 {
4683 ptrdiff_t bytepos = 0, position = 0, translated = 0; 4661 ptrdiff_t bytepos = 0, position = 0, translated = 0;
4684 ptrdiff_t fieldn = 1; 4662 ptrdiff_t fieldn = 0;
4685 4663
4686 /* Adjust the bounds of each text property 4664 /* Adjust the bounds of each text property
4687 to the proper start and end in the output string. */ 4665 to the proper start and end in the output string. */
@@ -4747,7 +4725,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4747 4725
4748 /* Add text properties from arguments. */ 4726 /* Add text properties from arguments. */
4749 if (arg_intervals) 4727 if (arg_intervals)
4750 for (ptrdiff_t i = 1; i <= num_percent; i++) 4728 for (ptrdiff_t i = 0; i < nspec; i++)
4751 if (info[i].intervals) 4729 if (info[i].intervals)
4752 { 4730 {
4753 len = make_number (SCHARS (info[i].argument)); 4731 len = make_number (SCHARS (info[i].argument));
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 33c5fbd484b..71e04d869e9 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -28,6 +28,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28#include "lisp.h" 28#include "lisp.h"
29#include "dynlib.h" 29#include "dynlib.h"
30#include "coding.h" 30#include "coding.h"
31#include "keyboard.h"
31#include "syssignal.h" 32#include "syssignal.h"
32 33
33#include <intprops.h> 34#include <intprops.h>
@@ -36,12 +37,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
36 37
37/* Feature tests. */ 38/* Feature tests. */
38 39
39#if __has_attribute (cleanup)
40enum { module_has_cleanup = true };
41#else
42enum { module_has_cleanup = false };
43#endif
44
45#ifdef WINDOWSNT 40#ifdef WINDOWSNT
46#include <windows.h> 41#include <windows.h>
47#include "w32term.h" 42#include "w32term.h"
@@ -88,8 +83,6 @@ struct emacs_env_private
88 environment. */ 83 environment. */
89struct emacs_runtime_private 84struct emacs_runtime_private
90{ 85{
91 /* FIXME: Ideally, we would just define "struct emacs_runtime_private"
92 as a synonym of "emacs_env", but I don't know how to do that in C. */
93 emacs_env pub; 86 emacs_env pub;
94}; 87};
95 88
@@ -102,8 +95,8 @@ static Lisp_Object value_to_lisp (emacs_value);
102static emacs_value lisp_to_value (Lisp_Object); 95static emacs_value lisp_to_value (Lisp_Object);
103static enum emacs_funcall_exit module_non_local_exit_check (emacs_env *); 96static enum emacs_funcall_exit module_non_local_exit_check (emacs_env *);
104static void check_main_thread (void); 97static void check_main_thread (void);
105static void finalize_environment (struct emacs_env_private *); 98static void initialize_environment (emacs_env *, struct emacs_env_private *);
106static void initialize_environment (emacs_env *, struct emacs_env_private *priv); 99static void finalize_environment (emacs_env *, struct emacs_env_private *);
107static void module_handle_signal (emacs_env *, Lisp_Object); 100static void module_handle_signal (emacs_env *, Lisp_Object);
108static void module_handle_throw (emacs_env *, Lisp_Object); 101static void module_handle_throw (emacs_env *, Lisp_Object);
109static void module_non_local_exit_signal_1 (emacs_env *, Lisp_Object, Lisp_Object); 102static void module_non_local_exit_signal_1 (emacs_env *, Lisp_Object, Lisp_Object);
@@ -169,7 +162,7 @@ static emacs_value const module_nil = 0;
169 module_out_of_memory (env); \ 162 module_out_of_memory (env); \
170 return retval; \ 163 return retval; \
171 } \ 164 } \
172 verify (module_has_cleanup); \ 165 verify (__has_attribute (cleanup)); \
173 struct handler *c __attribute__ ((cleanup (module_reset_handlerlist))) \ 166 struct handler *c __attribute__ ((cleanup (module_reset_handlerlist))) \
174 = c0; \ 167 = c0; \
175 if (sys_setjmp (c->jmp)) \ 168 if (sys_setjmp (c->jmp)) \
@@ -213,14 +206,24 @@ static emacs_value const module_nil = 0;
213 instead of reporting the error back to Lisp, and also because 206 instead of reporting the error back to Lisp, and also because
214 'eassert' is compiled to nothing in the release version. */ 207 'eassert' is compiled to nothing in the release version. */
215 208
209/* Use MODULE_FUNCTION_BEGIN_NO_CATCH to implement steps 2 and 3 for
210 environment functions that are known to never exit non-locally. On
211 error it will return its argument, which can be a sentinel
212 value. */
213
214#define MODULE_FUNCTION_BEGIN_NO_CATCH(error_retval) \
215 do { \
216 check_main_thread (); \
217 if (module_non_local_exit_check (env) != emacs_funcall_exit_return) \
218 return error_retval; \
219 } while (false)
220
216/* Use MODULE_FUNCTION_BEGIN to implement steps 2 through 4 for most 221/* Use MODULE_FUNCTION_BEGIN to implement steps 2 through 4 for most
217 environment functions. On error it will return its argument, which 222 environment functions. On error it will return its argument, which
218 should be a sentinel value. */ 223 can be a sentinel value. */
219 224
220#define MODULE_FUNCTION_BEGIN(error_retval) \ 225#define MODULE_FUNCTION_BEGIN(error_retval) \
221 check_main_thread (); \ 226 MODULE_FUNCTION_BEGIN_NO_CATCH (error_retval); \
222 if (module_non_local_exit_check (env) != emacs_funcall_exit_return) \
223 return error_retval; \
224 MODULE_HANDLE_NONLOCAL_EXIT (error_retval) 227 MODULE_HANDLE_NONLOCAL_EXIT (error_retval)
225 228
226static void 229static void
@@ -342,7 +345,7 @@ module_non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value)
342 value_to_lisp (value)); 345 value_to_lisp (value));
343} 346}
344 347
345/* A module function is a pseudovector of subtype type 348/* A module function is a pseudovector of subtype
346 PVEC_MODULE_FUNCTION; see lisp.h for the definition. */ 349 PVEC_MODULE_FUNCTION; see lisp.h for the definition. */
347 350
348static emacs_value 351static emacs_value
@@ -418,18 +421,14 @@ module_type_of (emacs_env *env, emacs_value value)
418static bool 421static bool
419module_is_not_nil (emacs_env *env, emacs_value value) 422module_is_not_nil (emacs_env *env, emacs_value value)
420{ 423{
421 check_main_thread (); 424 MODULE_FUNCTION_BEGIN_NO_CATCH (false);
422 if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
423 return false;
424 return ! NILP (value_to_lisp (value)); 425 return ! NILP (value_to_lisp (value));
425} 426}
426 427
427static bool 428static bool
428module_eq (emacs_env *env, emacs_value a, emacs_value b) 429module_eq (emacs_env *env, emacs_value a, emacs_value b)
429{ 430{
430 check_main_thread (); 431 MODULE_FUNCTION_BEGIN_NO_CATCH (false);
431 if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
432 return false;
433 return EQ (value_to_lisp (a), value_to_lisp (b)); 432 return EQ (value_to_lisp (a), value_to_lisp (b));
434} 433}
435 434
@@ -487,8 +486,6 @@ module_copy_string_contents (emacs_env *env, emacs_value value, char *buffer,
487 return true; 486 return true;
488 } 487 }
489 488
490 eassert (*length >= 0);
491
492 if (*length < required_buf_size) 489 if (*length < required_buf_size)
493 { 490 {
494 *length = required_buf_size; 491 *length = required_buf_size;
@@ -505,6 +502,8 @@ static emacs_value
505module_make_string (emacs_env *env, const char *str, ptrdiff_t length) 502module_make_string (emacs_env *env, const char *str, ptrdiff_t length)
506{ 503{
507 MODULE_FUNCTION_BEGIN (module_nil); 504 MODULE_FUNCTION_BEGIN (module_nil);
505 if (! (0 <= length && length <= STRING_BYTES_BOUND))
506 xsignal0 (Qoverflow_error);
508 AUTO_STRING_WITH_LEN (lstr, str, length); 507 AUTO_STRING_WITH_LEN (lstr, str, length);
509 return lisp_to_value (code_convert_string_norecord (lstr, Qutf_8, false)); 508 return lisp_to_value (code_convert_string_norecord (lstr, Qutf_8, false));
510} 509}
@@ -593,6 +592,15 @@ module_vec_size (emacs_env *env, emacs_value vec)
593 return ASIZE (lvec); 592 return ASIZE (lvec);
594} 593}
595 594
595/* This function should return true if and only if maybe_quit would do
596 anything. */
597static bool
598module_should_quit (emacs_env *env)
599{
600 MODULE_FUNCTION_BEGIN_NO_CATCH (false);
601 return (! NILP (Vquit_flag) && NILP (Vinhibit_quit)) || pending_signals;
602}
603
596 604
597/* Subroutines. */ 605/* Subroutines. */
598 606
@@ -607,15 +615,15 @@ DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0,
607 CHECK_STRING (file); 615 CHECK_STRING (file);
608 handle = dynlib_open (SSDATA (file)); 616 handle = dynlib_open (SSDATA (file));
609 if (!handle) 617 if (!handle)
610 error ("Cannot load file %s: %s", SDATA (file), dynlib_error ()); 618 xsignal2 (Qmodule_open_failed, file, build_string (dynlib_error ()));
611 619
612 gpl_sym = dynlib_sym (handle, "plugin_is_GPL_compatible"); 620 gpl_sym = dynlib_sym (handle, "plugin_is_GPL_compatible");
613 if (!gpl_sym) 621 if (!gpl_sym)
614 error ("Module %s is not GPL compatible", SDATA (file)); 622 xsignal1 (Qmodule_not_gpl_compatible, file);
615 623
616 module_init = (emacs_init_function) dynlib_func (handle, "emacs_module_init"); 624 module_init = (emacs_init_function) dynlib_func (handle, "emacs_module_init");
617 if (!module_init) 625 if (!module_init)
618 error ("Module %s does not have an init function.", SDATA (file)); 626 xsignal1 (Qmissing_module_init_function, file);
619 627
620 struct emacs_runtime_private rt; /* Includes the public emacs_env. */ 628 struct emacs_runtime_private rt; /* Includes the public emacs_env. */
621 struct emacs_env_private priv; 629 struct emacs_env_private priv;
@@ -627,34 +635,33 @@ DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0,
627 .get_environment = module_get_environment 635 .get_environment = module_get_environment
628 }; 636 };
629 int r = module_init (&pub); 637 int r = module_init (&pub);
630 finalize_environment (&priv); 638 finalize_environment (&rt.pub, &priv);
631 639
632 if (r != 0) 640 if (r != 0)
633 { 641 {
634 if (FIXNUM_OVERFLOW_P (r)) 642 if (FIXNUM_OVERFLOW_P (r))
635 xsignal0 (Qoverflow_error); 643 xsignal0 (Qoverflow_error);
636 xsignal2 (Qmodule_load_failed, file, make_number (r)); 644 xsignal2 (Qmodule_init_failed, file, make_number (r));
637 } 645 }
638 646
639 return Qt; 647 return Qt;
640} 648}
641 649
642Lisp_Object 650Lisp_Object
643funcall_module (const struct Lisp_Module_Function *const function, 651funcall_module (Lisp_Object function, ptrdiff_t nargs, Lisp_Object *arglist)
644 ptrdiff_t nargs, Lisp_Object *arglist)
645{ 652{
646 eassume (0 <= function->min_arity); 653 const struct Lisp_Module_Function *func = XMODULE_FUNCTION (function);
647 if (! (function->min_arity <= nargs 654 eassume (0 <= func->min_arity);
648 && (function->max_arity < 0 || nargs <= function->max_arity))) 655 if (! (func->min_arity <= nargs
649 xsignal2 (Qwrong_number_of_arguments, module_format_fun_env (function), 656 && (func->max_arity < 0 || nargs <= func->max_arity)))
650 make_number (nargs)); 657 xsignal2 (Qwrong_number_of_arguments, function, make_number (nargs));
651 658
652 emacs_env pub; 659 emacs_env pub;
653 struct emacs_env_private priv; 660 struct emacs_env_private priv;
654 initialize_environment (&pub, &priv); 661 initialize_environment (&pub, &priv);
655 662
656 USE_SAFE_ALLOCA; 663 USE_SAFE_ALLOCA;
657 emacs_value *args; 664 ATTRIBUTE_MAY_ALIAS emacs_value *args;
658 if (plain_values) 665 if (plain_values)
659 args = (emacs_value *) arglist; 666 args = (emacs_value *) arglist;
660 else 667 else
@@ -664,28 +671,32 @@ funcall_module (const struct Lisp_Module_Function *const function,
664 args[i] = lisp_to_value (arglist[i]); 671 args[i] = lisp_to_value (arglist[i]);
665 } 672 }
666 673
667 emacs_value ret = function->subr (&pub, nargs, args, function->data); 674 emacs_value ret = func->subr (&pub, nargs, args, func->data);
668 SAFE_FREE (); 675 SAFE_FREE ();
669 676
670 eassert (&priv == pub.private_members); 677 eassert (&priv == pub.private_members);
671 678
679 /* Process the quit flag first, so that quitting doesn't get
680 overridden by other non-local exits. */
681 maybe_quit ();
682
672 switch (priv.pending_non_local_exit) 683 switch (priv.pending_non_local_exit)
673 { 684 {
674 case emacs_funcall_exit_return: 685 case emacs_funcall_exit_return:
675 finalize_environment (&priv); 686 finalize_environment (&pub, &priv);
676 return value_to_lisp (ret); 687 return value_to_lisp (ret);
677 case emacs_funcall_exit_signal: 688 case emacs_funcall_exit_signal:
678 { 689 {
679 Lisp_Object symbol = priv.non_local_exit_symbol; 690 Lisp_Object symbol = priv.non_local_exit_symbol;
680 Lisp_Object data = priv.non_local_exit_data; 691 Lisp_Object data = priv.non_local_exit_data;
681 finalize_environment (&priv); 692 finalize_environment (&pub, &priv);
682 xsignal (symbol, data); 693 xsignal (symbol, data);
683 } 694 }
684 case emacs_funcall_exit_throw: 695 case emacs_funcall_exit_throw:
685 { 696 {
686 Lisp_Object tag = priv.non_local_exit_symbol; 697 Lisp_Object tag = priv.non_local_exit_symbol;
687 Lisp_Object value = priv.non_local_exit_data; 698 Lisp_Object value = priv.non_local_exit_data;
688 finalize_environment (&priv); 699 finalize_environment (&pub, &priv);
689 Fthrow (tag, value); 700 Fthrow (tag, value);
690 } 701 }
691 default: 702 default:
@@ -894,14 +905,17 @@ initialize_environment (emacs_env *env, struct emacs_env_private *priv)
894 env->vec_set = module_vec_set; 905 env->vec_set = module_vec_set;
895 env->vec_get = module_vec_get; 906 env->vec_get = module_vec_get;
896 env->vec_size = module_vec_size; 907 env->vec_size = module_vec_size;
908 env->should_quit = module_should_quit;
897 Vmodule_environments = Fcons (make_save_ptr (env), Vmodule_environments); 909 Vmodule_environments = Fcons (make_save_ptr (env), Vmodule_environments);
898} 910}
899 911
900/* Must be called before the lifetime of the environment object 912/* Must be called before the lifetime of the environment object
901 ends. */ 913 ends. */
902static void 914static void
903finalize_environment (struct emacs_env_private *env) 915finalize_environment (emacs_env *env, struct emacs_env_private *priv)
904{ 916{
917 eassert (env->private_members == priv);
918 eassert (XSAVE_POINTER (XCAR (Vmodule_environments), 0) == env);
905 Vmodule_environments = XCDR (Vmodule_environments); 919 Vmodule_environments = XCDR (Vmodule_environments);
906} 920}
907 921
@@ -937,35 +951,6 @@ module_handle_throw (emacs_env *env, Lisp_Object tag_val)
937} 951}
938 952
939 953
940/* Function environments. */
941
942/* Return a string object that contains a user-friendly
943 representation of the function environment. */
944Lisp_Object
945module_format_fun_env (const struct Lisp_Module_Function *env)
946{
947 /* Try to print a function name if possible. */
948 /* FIXME: Move this function into print.c, then use prin1-to-string
949 above. */
950 const char *path, *sym;
951 static char const noaddr_format[] = "#<module function at %p>";
952 char buffer[sizeof noaddr_format + INT_STRLEN_BOUND (intptr_t) + 256];
953 char *buf = buffer;
954 ptrdiff_t bufsize = sizeof buffer;
955 ptrdiff_t size
956 = (dynlib_addr (env->subr, &path, &sym)
957 ? exprintf (&buf, &bufsize, buffer, -1,
958 "#<module function %s from %s>", sym, path)
959 : sprintf (buffer, noaddr_format, env->subr));
960 AUTO_STRING_WITH_LEN (unibyte_result, buffer, size);
961 Lisp_Object result = code_convert_string_norecord (unibyte_result,
962 Qutf_8, false);
963 if (buf != buffer)
964 xfree (buf);
965 return result;
966}
967
968
969/* Segment initializer. */ 954/* Segment initializer. */
970 955
971void 956void
@@ -999,11 +984,34 @@ syms_of_module (void)
999 Fput (Qmodule_load_failed, Qerror_message, 984 Fput (Qmodule_load_failed, Qerror_message,
1000 build_pure_c_string ("Module load failed")); 985 build_pure_c_string ("Module load failed"));
1001 986
1002 DEFSYM (Qinvalid_module_call, "invalid-module-call"); 987 DEFSYM (Qmodule_open_failed, "module-open-failed");
1003 Fput (Qinvalid_module_call, Qerror_conditions, 988 Fput (Qmodule_open_failed, Qerror_conditions,
1004 listn (CONSTYPE_PURE, 2, Qinvalid_module_call, Qerror)); 989 listn (CONSTYPE_PURE, 3,
1005 Fput (Qinvalid_module_call, Qerror_message, 990 Qmodule_open_failed, Qmodule_load_failed, Qerror));
1006 build_pure_c_string ("Invalid module call")); 991 Fput (Qmodule_open_failed, Qerror_message,
992 build_pure_c_string ("Module could not be opened"));
993
994 DEFSYM (Qmodule_not_gpl_compatible, "module-not-gpl-compatible");
995 Fput (Qmodule_not_gpl_compatible, Qerror_conditions,
996 listn (CONSTYPE_PURE, 3,
997 Qmodule_not_gpl_compatible, Qmodule_load_failed, Qerror));
998 Fput (Qmodule_not_gpl_compatible, Qerror_message,
999 build_pure_c_string ("Module is not GPL compatible"));
1000
1001 DEFSYM (Qmissing_module_init_function, "missing-module-init-function");
1002 Fput (Qmissing_module_init_function, Qerror_conditions,
1003 listn (CONSTYPE_PURE, 3,
1004 Qmissing_module_init_function, Qmodule_load_failed, Qerror));
1005 Fput (Qmissing_module_init_function, Qerror_message,
1006 build_pure_c_string ("Module does not export an "
1007 "initialization function"));
1008
1009 DEFSYM (Qmodule_init_failed, "module-init-failed");
1010 Fput (Qmodule_init_failed, Qerror_conditions,
1011 listn (CONSTYPE_PURE, 3,
1012 Qmodule_init_failed, Qmodule_load_failed, Qerror));
1013 Fput (Qmodule_init_failed, Qerror_message,
1014 build_pure_c_string ("Module initialization failed"));
1007 1015
1008 DEFSYM (Qinvalid_arity, "invalid-arity"); 1016 DEFSYM (Qinvalid_arity, "invalid-arity");
1009 Fput (Qinvalid_arity, Qerror_conditions, 1017 Fput (Qinvalid_arity, Qerror_conditions,
diff --git a/src/emacs-module.h b/src/emacs-module.h
index d9eeeabec3f..b8bf2ed2d5f 100644
--- a/src/emacs-module.h
+++ b/src/emacs-module.h
@@ -185,6 +185,9 @@ struct emacs_env_25
185 emacs_value val); 185 emacs_value val);
186 186
187 ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vec); 187 ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vec);
188
189 /* Returns whether a quit is pending. */
190 bool (*should_quit) (emacs_env *env);
188}; 191};
189 192
190/* Every module should define a function as follows. */ 193/* Every module should define a function as follows. */
diff --git a/src/eval.c b/src/eval.c
index f472efad52e..ef961046bcf 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1474,7 +1474,10 @@ process_quit_flag (void)
1474 If quit-flag is set to `kill-emacs' the SIGINT handler has received 1474 If quit-flag is set to `kill-emacs' the SIGINT handler has received
1475 a request to exit Emacs when it is safe to do. 1475 a request to exit Emacs when it is safe to do.
1476 1476
1477 When not quitting, process any pending signals. */ 1477 When not quitting, process any pending signals.
1478
1479 If you change this function, also adapt module_should_quit in
1480 emacs-module.c. */
1478 1481
1479void 1482void
1480maybe_quit (void) 1483maybe_quit (void)
@@ -2952,7 +2955,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
2952 } 2955 }
2953#ifdef HAVE_MODULES 2956#ifdef HAVE_MODULES
2954 else if (MODULE_FUNCTIONP (fun)) 2957 else if (MODULE_FUNCTIONP (fun))
2955 return funcall_module (XMODULE_FUNCTION (fun), nargs, arg_vector); 2958 return funcall_module (fun, nargs, arg_vector);
2956#endif 2959#endif
2957 else 2960 else
2958 emacs_abort (); 2961 emacs_abort ();
diff --git a/src/lisp.h b/src/lisp.h
index 7b8f1e754d8..c35bd1f6df1 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1346,7 +1346,9 @@ SSET (Lisp_Object string, ptrdiff_t index, unsigned char new)
1346INLINE ptrdiff_t 1346INLINE ptrdiff_t
1347SCHARS (Lisp_Object string) 1347SCHARS (Lisp_Object string)
1348{ 1348{
1349 return XSTRING (string)->size; 1349 ptrdiff_t nchars = XSTRING (string)->size;
1350 eassume (0 <= nchars);
1351 return nchars;
1350} 1352}
1351 1353
1352#ifdef GC_CHECK_STRING_BYTES 1354#ifdef GC_CHECK_STRING_BYTES
@@ -1356,10 +1358,12 @@ INLINE ptrdiff_t
1356STRING_BYTES (struct Lisp_String *s) 1358STRING_BYTES (struct Lisp_String *s)
1357{ 1359{
1358#ifdef GC_CHECK_STRING_BYTES 1360#ifdef GC_CHECK_STRING_BYTES
1359 return string_bytes (s); 1361 ptrdiff_t nbytes = string_bytes (s);
1360#else 1362#else
1361 return s->size_byte < 0 ? s->size : s->size_byte; 1363 ptrdiff_t nbytes = s->size_byte < 0 ? s->size : s->size_byte;
1362#endif 1364#endif
1365 eassume (0 <= nbytes);
1366 return nbytes;
1363} 1367}
1364 1368
1365INLINE ptrdiff_t 1369INLINE ptrdiff_t
@@ -1373,7 +1377,7 @@ STRING_SET_CHARS (Lisp_Object string, ptrdiff_t newsize)
1373 /* This function cannot change the size of data allocated for the 1377 /* This function cannot change the size of data allocated for the
1374 string when it was created. */ 1378 string when it was created. */
1375 eassert (STRING_MULTIBYTE (string) 1379 eassert (STRING_MULTIBYTE (string)
1376 ? newsize <= SBYTES (string) 1380 ? 0 <= newsize && newsize <= SBYTES (string)
1377 : newsize == SCHARS (string)); 1381 : newsize == SCHARS (string));
1378 XSTRING (string)->size = newsize; 1382 XSTRING (string)->size = newsize;
1379} 1383}
@@ -3952,10 +3956,8 @@ XMODULE_FUNCTION (Lisp_Object o)
3952extern Lisp_Object make_user_ptr (void (*finalizer) (void *), void *p); 3956extern Lisp_Object make_user_ptr (void (*finalizer) (void *), void *p);
3953 3957
3954/* Defined in emacs-module.c. */ 3958/* Defined in emacs-module.c. */
3955extern Lisp_Object funcall_module (const struct Lisp_Module_Function *, 3959extern Lisp_Object funcall_module (Lisp_Object, ptrdiff_t, Lisp_Object *);
3956 ptrdiff_t, Lisp_Object *);
3957extern Lisp_Object module_function_arity (const struct Lisp_Module_Function *); 3960extern Lisp_Object module_function_arity (const struct Lisp_Module_Function *);
3958extern Lisp_Object module_format_fun_env (const struct Lisp_Module_Function *);
3959extern void syms_of_module (void); 3961extern void syms_of_module (void);
3960#endif 3962#endif
3961 3963
diff --git a/src/print.c b/src/print.c
index 49408bbeb40..76ae10fe132 100644
--- a/src/print.c
+++ b/src/print.c
@@ -33,6 +33,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
33#include "intervals.h" 33#include "intervals.h"
34#include "blockinput.h" 34#include "blockinput.h"
35#include "xwidget.h" 35#include "xwidget.h"
36#include "dynlib.h"
36 37
37#include <c-ctype.h> 38#include <c-ctype.h>
38#include <float.h> 39#include <float.h>
@@ -1699,8 +1700,33 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
1699 1700
1700#ifdef HAVE_MODULES 1701#ifdef HAVE_MODULES
1701 case PVEC_MODULE_FUNCTION: 1702 case PVEC_MODULE_FUNCTION:
1702 print_string (module_format_fun_env (XMODULE_FUNCTION (obj)), 1703 {
1703 printcharfun); 1704 print_c_string ("#<module function ", printcharfun);
1705 void *ptr = XMODULE_FUNCTION (obj)->subr;
1706 const char *file = NULL;
1707 const char *symbol = NULL;
1708 dynlib_addr (ptr, &file, &symbol);
1709
1710 if (symbol == NULL)
1711 {
1712 print_c_string ("at ", printcharfun);
1713 enum { pointer_bufsize = sizeof ptr * 16 / CHAR_BIT + 2 + 1 };
1714 char buffer[pointer_bufsize];
1715 int needed = snprintf (buffer, sizeof buffer, "%p", ptr);
1716 eassert (needed <= sizeof buffer);
1717 print_c_string (buffer, printcharfun);
1718 }
1719 else
1720 print_c_string (symbol, printcharfun);
1721
1722 if (file != NULL)
1723 {
1724 print_c_string (" from ", printcharfun);
1725 print_c_string (file, printcharfun);
1726 }
1727
1728 printchar ('>', printcharfun);
1729 }
1704 break; 1730 break;
1705#endif 1731#endif
1706 1732