diff options
| author | Paul Eggert | 2019-05-05 17:35:05 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-05-05 17:40:55 -0700 |
| commit | 926a394997eaae55b797a90cb2cd037bbe3c3db4 (patch) | |
| tree | a075ef40927dc732c254f2d63a98af8ca3d99c82 | |
| parent | 31c60dfbd8541c9f1b1bc8127dde85e5d5af51b5 (diff) | |
| download | emacs-926a394997eaae55b797a90cb2cd037bbe3c3db4.tar.gz emacs-926a394997eaae55b797a90cb2cd037bbe3c3db4.zip | |
Use simpler way to print function pointers
The module code can’t possibly work on weird platforms where
function pointers are wider than data pointers, so there’s no need
to bother with the stackoverflow-like approach that is intended
only for portability to such platforms. Besides, the
stackoverflow-like approach does not work well on weird platforms
where CHAR_BIT is not a multiple of 4.
* src/lisp.h (pMx): New macro.
* src/print.c (data_from_funcptr) [HAVE_MODULES]: New function.
(print_vectorlike) [HAVE_MODULES]: Use it.
(print_object): Make sure buf is big enough for this.
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/print.c | 47 |
2 files changed, 28 insertions, 21 deletions
diff --git a/src/lisp.h b/src/lisp.h index ca833476c03..61cc20e9d42 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -144,11 +144,13 @@ typedef intmax_t printmax_t; | |||
| 144 | typedef uintmax_t uprintmax_t; | 144 | typedef uintmax_t uprintmax_t; |
| 145 | # define pMd PRIdMAX | 145 | # define pMd PRIdMAX |
| 146 | # define pMu PRIuMAX | 146 | # define pMu PRIuMAX |
| 147 | # define pMx PRIxMAX | ||
| 147 | #else | 148 | #else |
| 148 | typedef EMACS_INT printmax_t; | 149 | typedef EMACS_INT printmax_t; |
| 149 | typedef EMACS_UINT uprintmax_t; | 150 | typedef EMACS_UINT uprintmax_t; |
| 150 | # define pMd pI"d" | 151 | # define pMd pI"d" |
| 151 | # define pMu pI"u" | 152 | # define pMu pI"u" |
| 153 | # define pMx pI"x" | ||
| 152 | #endif | 154 | #endif |
| 153 | 155 | ||
| 154 | /* Use pD to format ptrdiff_t values, which suffice for indexes into | 156 | /* Use pD to format ptrdiff_t values, which suffice for indexes into |
diff --git a/src/print.c b/src/print.c index 08c39d34664..406abbf4a3f 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -1361,6 +1361,19 @@ print_prune_string_charset (Lisp_Object string) | |||
| 1361 | return string; | 1361 | return string; |
| 1362 | } | 1362 | } |
| 1363 | 1363 | ||
| 1364 | #ifdef HAVE_MODULES | ||
| 1365 | /* Return a data pointer equal to FUNCPTR. */ | ||
| 1366 | |||
| 1367 | static void const * | ||
| 1368 | data_from_funcptr (void (*funcptr) (void)) | ||
| 1369 | { | ||
| 1370 | /* The module code, and the POSIX API for dynamic linking, already | ||
| 1371 | assume that function and data pointers are represented | ||
| 1372 | interchangeably, so it's OK to assume that here too. */ | ||
| 1373 | return (void const *) funcptr; | ||
| 1374 | } | ||
| 1375 | #endif | ||
| 1376 | |||
| 1364 | static bool | 1377 | static bool |
| 1365 | print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, | 1378 | print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, |
| 1366 | char *buf) | 1379 | char *buf) |
| @@ -1788,30 +1801,20 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, | |||
| 1788 | { | 1801 | { |
| 1789 | print_c_string ("#<module function ", printcharfun); | 1802 | print_c_string ("#<module function ", printcharfun); |
| 1790 | module_funcptr ptr = module_function_address (XMODULE_FUNCTION (obj)); | 1803 | module_funcptr ptr = module_function_address (XMODULE_FUNCTION (obj)); |
| 1791 | const char *file = NULL; | 1804 | char const *file; |
| 1792 | const char *symbol = NULL; | 1805 | char const *symbol; |
| 1793 | dynlib_addr (ptr, &file, &symbol); | 1806 | dynlib_addr (ptr, &file, &symbol); |
| 1794 | 1807 | ||
| 1795 | if (symbol == NULL) | 1808 | if (symbol == NULL) |
| 1796 | { | 1809 | { |
| 1797 | print_c_string ("at 0x", printcharfun); | 1810 | uintptr_t ui = (uintptr_t) data_from_funcptr (ptr); |
| 1798 | /* See https://stackoverflow.com/a/2741896 for how to | 1811 | |
| 1799 | portably print a function pointer. */ | 1812 | /* In theory this assignment could lose info on pre-C99 |
| 1800 | const unsigned char *p = (const unsigned char *) &ptr; | 1813 | hosts, but in practice it doesn't. */ |
| 1801 | for (size_t i = 0; i < sizeof ptr; ++i) | 1814 | uprintmax_t up = ui; |
| 1802 | { | 1815 | |
| 1803 | #ifdef WORDS_BIGENDIAN | 1816 | int len = sprintf (buf, "at 0x%"pMx, up); |
| 1804 | unsigned char b = p[i]; | 1817 | strout (buf, len, len, printcharfun); |
| 1805 | #else | ||
| 1806 | unsigned char b = p[sizeof ptr - i - 1]; | ||
| 1807 | #endif | ||
| 1808 | enum { digits = (CHAR_BIT + 4 - 1) / 4 }; | ||
| 1809 | char buffer[digits + 1]; | ||
| 1810 | int needed | ||
| 1811 | = snprintf (buffer, sizeof buffer, "%0*x", digits, b); | ||
| 1812 | eassert (needed == digits); | ||
| 1813 | print_c_string (buffer, printcharfun); | ||
| 1814 | } | ||
| 1815 | } | 1818 | } |
| 1816 | else | 1819 | else |
| 1817 | print_c_string (symbol, printcharfun); | 1820 | print_c_string (symbol, printcharfun); |
| @@ -1839,7 +1842,9 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 1839 | { | 1842 | { |
| 1840 | char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT), | 1843 | char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT), |
| 1841 | max (sizeof " . #" + INT_STRLEN_BOUND (printmax_t), | 1844 | max (sizeof " . #" + INT_STRLEN_BOUND (printmax_t), |
| 1842 | 40))]; | 1845 | max ((sizeof "at 0x" |
| 1846 | + (sizeof (uprintmax_t) * CHAR_BIT + 4 - 1) / 4), | ||
| 1847 | 40)))]; | ||
| 1843 | current_thread->stack_top = buf; | 1848 | current_thread->stack_top = buf; |
| 1844 | maybe_quit (); | 1849 | maybe_quit (); |
| 1845 | 1850 | ||