diff options
| author | Eli Zaretskii | 2017-12-10 18:36:37 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2017-12-10 18:36:37 +0200 |
| commit | 2b8a1b76920dbdfc39dab2ec29ab7650bf779275 (patch) | |
| tree | 2080a70b7238f63578d103dae8331e24840edc1c | |
| parent | f856d1e4489eac45afab865838abb2b16fb1f14f (diff) | |
| download | emacs-2b8a1b76920dbdfc39dab2ec29ab7650bf779275.tar.gz emacs-2b8a1b76920dbdfc39dab2ec29ab7650bf779275.zip | |
Support dynamic loading of libjansson on MS-Windows
* src/json.c [WINDOWSNT]: Define fn_* function pointers to jansson
functions.
(json_delete) [WINDOWSNT]: A wrapper around fn_json_delete, needed
by json_decref.
(init_json_functions) [WINDOWSNT]: New function.
(Fjson_serialize, Fjson_insert, Fjson_parse_string)
(Fjson_parse_buffer) [WINDOWSNT]: Call init_json_functions if
needed, and record JSON in Vlibrary_cache.
* src/emacs.c (main): Don't call init_json on WINDOWSNT.
* src/w32fns.c (syms_of_w32fns): DEFSYM "json".
* lisp/term/w32-win.el (dynamic-library-alist): Add JSON DLL to
the list.
* configure.ac (HAVE_JSON): Empty JSON_LIBS for MinGW.
* nt/INSTALL.W64:
* nt/INSTALL: Add information about libjansson.
| -rw-r--r-- | configure.ac | 5 | ||||
| -rw-r--r-- | lisp/term/w32-win.el | 3 | ||||
| -rw-r--r-- | nt/INSTALL | 7 | ||||
| -rw-r--r-- | nt/INSTALL.W64 | 1 | ||||
| -rw-r--r-- | src/emacs.c | 2 | ||||
| -rw-r--r-- | src/json.c | 181 | ||||
| -rw-r--r-- | src/w32fns.c | 1 |
7 files changed, 198 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac index caee0159548..562b19afe64 100644 --- a/configure.ac +++ b/configure.ac | |||
| @@ -2881,6 +2881,11 @@ if test "${with_json}" = yes; then | |||
| 2881 | AC_DEFINE(HAVE_JSON, 1, [Define if using Jansson.]) | 2881 | AC_DEFINE(HAVE_JSON, 1, [Define if using Jansson.]) |
| 2882 | JSON_OBJ=json.o | 2882 | JSON_OBJ=json.o |
| 2883 | fi | 2883 | fi |
| 2884 | |||
| 2885 | # Windows loads libjansson dynamically | ||
| 2886 | if test "${opsys}" = "mingw32"; then | ||
| 2887 | JSON_LIBS= | ||
| 2888 | fi | ||
| 2884 | fi | 2889 | fi |
| 2885 | 2890 | ||
| 2886 | AC_SUBST(JSON_LIBS) | 2891 | AC_SUBST(JSON_LIBS) |
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el index 4e0e54ae179..1db90aec984 100644 --- a/lisp/term/w32-win.el +++ b/lisp/term/w32-win.el | |||
| @@ -276,7 +276,8 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") | |||
| 276 | '(gnutls "libgnutls-28.dll" "libgnutls-26.dll")) | 276 | '(gnutls "libgnutls-28.dll" "libgnutls-26.dll")) |
| 277 | '(libxml2 "libxml2-2.dll" "libxml2.dll") | 277 | '(libxml2 "libxml2-2.dll" "libxml2.dll") |
| 278 | '(zlib "zlib1.dll" "libz-1.dll") | 278 | '(zlib "zlib1.dll" "libz-1.dll") |
| 279 | '(lcms2 "liblcms2-2.dll"))) | 279 | '(lcms2 "liblcms2-2.dll") |
| 280 | '(json "libjansson-4.dll"))) | ||
| 280 | 281 | ||
| 281 | ;;; multi-tty support | 282 | ;;; multi-tty support |
| 282 | (defvar w32-initialized nil | 283 | (defvar w32-initialized nil |
diff --git a/nt/INSTALL b/nt/INSTALL index 30e14293f5c..361d607ff68 100644 --- a/nt/INSTALL +++ b/nt/INSTALL | |||
| @@ -806,6 +806,13 @@ build will run on Windows 9X and newer systems). | |||
| 806 | Prebuilt binaries of lcms2 DLL (for 32-bit builds of Emacs) are | 806 | Prebuilt binaries of lcms2 DLL (for 32-bit builds of Emacs) are |
| 807 | available from the ezwinports site and from the MSYS2 project. | 807 | available from the ezwinports site and from the MSYS2 project. |
| 808 | 808 | ||
| 809 | * Optional support for JSON | ||
| 810 | |||
| 811 | Emacs can provide built-in support for JSON parsing and | ||
| 812 | serialization using the libjansson library. Prebuilt binaries of | ||
| 813 | the libjansson DLL (for 32-bit builds of Emacs) are available from | ||
| 814 | the ezwinports site and from the MSYS2 project. | ||
| 815 | |||
| 809 | 816 | ||
| 810 | This file is part of GNU Emacs. | 817 | This file is part of GNU Emacs. |
| 811 | 818 | ||
diff --git a/nt/INSTALL.W64 b/nt/INSTALL.W64 index e08b72f2ca0..41d57bd3689 100644 --- a/nt/INSTALL.W64 +++ b/nt/INSTALL.W64 | |||
| @@ -52,6 +52,7 @@ packages (you can copy and paste it into the shell with Shift + Insert): | |||
| 52 | mingw-w64-x86_64-libjpeg-turbo \ | 52 | mingw-w64-x86_64-libjpeg-turbo \ |
| 53 | mingw-w64-x86_64-librsvg \ | 53 | mingw-w64-x86_64-librsvg \ |
| 54 | mingw-w64-x86_64-lcms2 \ | 54 | mingw-w64-x86_64-lcms2 \ |
| 55 | mingw-w64-x86_64-jansson \ | ||
| 55 | mingw-w64-x86_64-libxml2 \ | 56 | mingw-w64-x86_64-libxml2 \ |
| 56 | mingw-w64-x86_64-gnutls \ | 57 | mingw-w64-x86_64-gnutls \ |
| 57 | mingw-w64-x86_64-zlib | 58 | mingw-w64-x86_64-zlib |
diff --git a/src/emacs.c b/src/emacs.c index 7c1ae1f2c5b..5a6b896ef47 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -1262,7 +1262,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1262 | running_asynch_code = 0; | 1262 | running_asynch_code = 0; |
| 1263 | init_random (); | 1263 | init_random (); |
| 1264 | 1264 | ||
| 1265 | #ifdef HAVE_JSON | 1265 | #if defined HAVE_JSON && !defined WINDOWSNT |
| 1266 | init_json (); | 1266 | init_json (); |
| 1267 | #endif | 1267 | #endif |
| 1268 | 1268 | ||
diff --git a/src/json.c b/src/json.c index dc449e43e11..7025ae165cd 100644 --- a/src/json.c +++ b/src/json.c | |||
| @@ -30,6 +30,126 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 30 | #include "buffer.h" | 30 | #include "buffer.h" |
| 31 | #include "coding.h" | 31 | #include "coding.h" |
| 32 | 32 | ||
| 33 | #ifdef WINDOWSNT | ||
| 34 | # include <windows.h> | ||
| 35 | # include "w32.h" | ||
| 36 | |||
| 37 | DEF_DLL_FN (void, json_set_alloc_funcs, | ||
| 38 | (json_malloc_t malloc_fn, json_free_t free_fn)); | ||
| 39 | DEF_DLL_FN (void, json_delete, (json_t *json)); | ||
| 40 | DEF_DLL_FN (json_t *, json_array, (void)); | ||
| 41 | DEF_DLL_FN (int, json_array_append_new, (json_t *array, json_t *value)); | ||
| 42 | DEF_DLL_FN (size_t, json_array_size, (const json_t *array)); | ||
| 43 | DEF_DLL_FN (json_t *, json_object, (void)); | ||
| 44 | DEF_DLL_FN (int, json_object_set_new, | ||
| 45 | (json_t *object, const char *key, json_t *value)); | ||
| 46 | DEF_DLL_FN (json_t *, json_null, (void)); | ||
| 47 | DEF_DLL_FN (json_t *, json_true, (void)); | ||
| 48 | DEF_DLL_FN (json_t *, json_false, (void)); | ||
| 49 | DEF_DLL_FN (json_t *, json_integer, (json_int_t value)); | ||
| 50 | DEF_DLL_FN (json_t *, json_real, (double value)); | ||
| 51 | DEF_DLL_FN (json_t *, json_stringn, (const char *value, size_t len)); | ||
| 52 | DEF_DLL_FN (char *, json_dumps, (const json_t *json, size_t flags)); | ||
| 53 | DEF_DLL_FN (int, json_dump_callback, | ||
| 54 | (const json_t *json, json_dump_callback_t callback, void *data, | ||
| 55 | size_t flags)); | ||
| 56 | DEF_DLL_FN (json_int_t, json_integer_value, (const json_t *integer)); | ||
| 57 | DEF_DLL_FN (double, json_real_value, (const json_t *real)); | ||
| 58 | DEF_DLL_FN (const char *, json_string_value, (const json_t *string)); | ||
| 59 | DEF_DLL_FN (size_t, json_string_length, (const json_t *string)); | ||
| 60 | DEF_DLL_FN (json_t *, json_array_get, (const json_t *array, size_t index)); | ||
| 61 | DEF_DLL_FN (size_t, json_object_size, (const json_t *object)); | ||
| 62 | DEF_DLL_FN (const char *, json_object_iter_key, (void *iter)); | ||
| 63 | DEF_DLL_FN (void *, json_object_iter, (json_t *object)); | ||
| 64 | DEF_DLL_FN (json_t *, json_object_iter_value, (void *iter)); | ||
| 65 | DEF_DLL_FN (void *, json_object_key_to_iter, (const char *key)); | ||
| 66 | DEF_DLL_FN (void *, json_object_iter_next, (json_t *object, void *iter)); | ||
| 67 | DEF_DLL_FN (json_t *, json_loads, | ||
| 68 | (const char *input, size_t flags, json_error_t *error)); | ||
| 69 | DEF_DLL_FN (json_t *, json_load_callback, | ||
| 70 | (json_load_callback_t callback, void *data, size_t flags, | ||
| 71 | json_error_t *error)); | ||
| 72 | |||
| 73 | /* This is called by json_decref, which is an inline function. */ | ||
| 74 | void json_delete(json_t *json) | ||
| 75 | { | ||
| 76 | fn_json_delete (json); | ||
| 77 | } | ||
| 78 | |||
| 79 | static bool json_initialized; | ||
| 80 | |||
| 81 | static bool | ||
| 82 | init_json_functions (void) | ||
| 83 | { | ||
| 84 | HMODULE library = w32_delayed_load (Qjson); | ||
| 85 | |||
| 86 | if (!library) | ||
| 87 | return false; | ||
| 88 | |||
| 89 | LOAD_DLL_FN (library, json_set_alloc_funcs); | ||
| 90 | LOAD_DLL_FN (library, json_delete); | ||
| 91 | LOAD_DLL_FN (library, json_array); | ||
| 92 | LOAD_DLL_FN (library, json_array_append_new); | ||
| 93 | LOAD_DLL_FN (library, json_array_size); | ||
| 94 | LOAD_DLL_FN (library, json_object); | ||
| 95 | LOAD_DLL_FN (library, json_object_set_new); | ||
| 96 | LOAD_DLL_FN (library, json_null); | ||
| 97 | LOAD_DLL_FN (library, json_true); | ||
| 98 | LOAD_DLL_FN (library, json_false); | ||
| 99 | LOAD_DLL_FN (library, json_integer); | ||
| 100 | LOAD_DLL_FN (library, json_real); | ||
| 101 | LOAD_DLL_FN (library, json_stringn); | ||
| 102 | LOAD_DLL_FN (library, json_dumps); | ||
| 103 | LOAD_DLL_FN (library, json_dump_callback); | ||
| 104 | LOAD_DLL_FN (library, json_integer_value); | ||
| 105 | LOAD_DLL_FN (library, json_real_value); | ||
| 106 | LOAD_DLL_FN (library, json_string_value); | ||
| 107 | LOAD_DLL_FN (library, json_string_length); | ||
| 108 | LOAD_DLL_FN (library, json_array_get); | ||
| 109 | LOAD_DLL_FN (library, json_object_size); | ||
| 110 | LOAD_DLL_FN (library, json_object_iter_key); | ||
| 111 | LOAD_DLL_FN (library, json_object_iter); | ||
| 112 | LOAD_DLL_FN (library, json_object_iter_value); | ||
| 113 | LOAD_DLL_FN (library, json_object_key_to_iter); | ||
| 114 | LOAD_DLL_FN (library, json_object_iter_next); | ||
| 115 | LOAD_DLL_FN (library, json_loads); | ||
| 116 | LOAD_DLL_FN (library, json_load_callback); | ||
| 117 | |||
| 118 | init_json (); | ||
| 119 | |||
| 120 | return true; | ||
| 121 | } | ||
| 122 | |||
| 123 | #define json_set_alloc_funcs fn_json_set_alloc_funcs | ||
| 124 | #define json_array fn_json_array | ||
| 125 | #define json_array_append_new fn_json_array_append_new | ||
| 126 | #define json_array_size fn_json_array_size | ||
| 127 | #define json_object fn_json_object | ||
| 128 | #define json_object_set_new fn_json_object_set_new | ||
| 129 | #define json_null fn_json_null | ||
| 130 | #define json_true fn_json_true | ||
| 131 | #define json_false fn_json_false | ||
| 132 | #define json_integer fn_json_integer | ||
| 133 | #define json_real fn_json_real | ||
| 134 | #define json_stringn fn_json_stringn | ||
| 135 | #define json_dumps fn_json_dumps | ||
| 136 | #define json_dump_callback fn_json_dump_callback | ||
| 137 | #define json_integer_value fn_json_integer_value | ||
| 138 | #define json_real_value fn_json_real_value | ||
| 139 | #define json_string_value fn_json_string_value | ||
| 140 | #define json_string_length fn_json_string_length | ||
| 141 | #define json_array_get fn_json_array_get | ||
| 142 | #define json_object_size fn_json_object_size | ||
| 143 | #define json_object_iter_key fn_json_object_iter_key | ||
| 144 | #define json_object_iter fn_json_object_iter | ||
| 145 | #define json_object_iter_value fn_json_object_iter_value | ||
| 146 | #define json_object_key_to_iter fn_json_object_key_to_iter | ||
| 147 | #define json_object_iter_next fn_json_object_iter_next | ||
| 148 | #define json_loads fn_json_loads | ||
| 149 | #define json_load_callback fn_json_load_callback | ||
| 150 | |||
| 151 | #endif /* WINDOWSNT */ | ||
| 152 | |||
| 33 | /* We install a custom allocator so that we can avoid objects larger | 153 | /* We install a custom allocator so that we can avoid objects larger |
| 34 | than PTRDIFF_MAX. Such objects wouldn’t play well with the rest of | 154 | than PTRDIFF_MAX. Such objects wouldn’t play well with the rest of |
| 35 | Emacs’s codebase, which generally uses ptrdiff_t for sizes and | 155 | Emacs’s codebase, which generally uses ptrdiff_t for sizes and |
| @@ -277,6 +397,21 @@ each object. */) | |||
| 277 | { | 397 | { |
| 278 | ptrdiff_t count = SPECPDL_INDEX (); | 398 | ptrdiff_t count = SPECPDL_INDEX (); |
| 279 | 399 | ||
| 400 | #ifdef WINDOWSNT | ||
| 401 | if (!json_initialized) | ||
| 402 | { | ||
| 403 | Lisp_Object status; | ||
| 404 | json_initialized = init_json_functions (); | ||
| 405 | status = json_initialized ? Qt : Qnil; | ||
| 406 | Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache); | ||
| 407 | } | ||
| 408 | if (!json_initialized) | ||
| 409 | { | ||
| 410 | message1 ("jansson library not found"); | ||
| 411 | return Qnil; | ||
| 412 | } | ||
| 413 | #endif | ||
| 414 | |||
| 280 | json_t *json = lisp_to_json_toplevel (object); | 415 | json_t *json = lisp_to_json_toplevel (object); |
| 281 | record_unwind_protect_ptr (json_release_object, json); | 416 | record_unwind_protect_ptr (json_release_object, json); |
| 282 | 417 | ||
| @@ -340,6 +475,21 @@ OBJECT. */) | |||
| 340 | { | 475 | { |
| 341 | ptrdiff_t count = SPECPDL_INDEX (); | 476 | ptrdiff_t count = SPECPDL_INDEX (); |
| 342 | 477 | ||
| 478 | #ifdef WINDOWSNT | ||
| 479 | if (!json_initialized) | ||
| 480 | { | ||
| 481 | Lisp_Object status; | ||
| 482 | json_initialized = init_json_functions (); | ||
| 483 | status = json_initialized ? Qt : Qnil; | ||
| 484 | Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache); | ||
| 485 | } | ||
| 486 | if (!json_initialized) | ||
| 487 | { | ||
| 488 | message1 ("jansson library not found"); | ||
| 489 | return Qnil; | ||
| 490 | } | ||
| 491 | #endif | ||
| 492 | |||
| 343 | json_t *json = lisp_to_json (object); | 493 | json_t *json = lisp_to_json (object); |
| 344 | record_unwind_protect_ptr (json_release_object, json); | 494 | record_unwind_protect_ptr (json_release_object, json); |
| 345 | 495 | ||
| @@ -439,6 +589,22 @@ an error of type `json-parse-error' is signaled. */) | |||
| 439 | (Lisp_Object string) | 589 | (Lisp_Object string) |
| 440 | { | 590 | { |
| 441 | ptrdiff_t count = SPECPDL_INDEX (); | 591 | ptrdiff_t count = SPECPDL_INDEX (); |
| 592 | |||
| 593 | #ifdef WINDOWSNT | ||
| 594 | if (!json_initialized) | ||
| 595 | { | ||
| 596 | Lisp_Object status; | ||
| 597 | json_initialized = init_json_functions (); | ||
| 598 | status = json_initialized ? Qt : Qnil; | ||
| 599 | Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache); | ||
| 600 | } | ||
| 601 | if (!json_initialized) | ||
| 602 | { | ||
| 603 | message1 ("jansson library not found"); | ||
| 604 | return Qnil; | ||
| 605 | } | ||
| 606 | #endif | ||
| 607 | |||
| 442 | Lisp_Object encoded = json_encode (string); | 608 | Lisp_Object encoded = json_encode (string); |
| 443 | check_string_without_embedded_nulls (encoded); | 609 | check_string_without_embedded_nulls (encoded); |
| 444 | 610 | ||
| @@ -493,6 +659,21 @@ not moved. */) | |||
| 493 | { | 659 | { |
| 494 | ptrdiff_t count = SPECPDL_INDEX (); | 660 | ptrdiff_t count = SPECPDL_INDEX (); |
| 495 | 661 | ||
| 662 | #ifdef WINDOWSNT | ||
| 663 | if (!json_initialized) | ||
| 664 | { | ||
| 665 | Lisp_Object status; | ||
| 666 | json_initialized = init_json_functions (); | ||
| 667 | status = json_initialized ? Qt : Qnil; | ||
| 668 | Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache); | ||
| 669 | } | ||
| 670 | if (!json_initialized) | ||
| 671 | { | ||
| 672 | message1 ("jansson library not found"); | ||
| 673 | return Qnil; | ||
| 674 | } | ||
| 675 | #endif | ||
| 676 | |||
| 496 | ptrdiff_t point = PT_BYTE; | 677 | ptrdiff_t point = PT_BYTE; |
| 497 | struct json_read_buffer_data data = {.point = point}; | 678 | struct json_read_buffer_data data = {.point = point}; |
| 498 | json_error_t error; | 679 | json_error_t error; |
diff --git a/src/w32fns.c b/src/w32fns.c index d2d4b2c7355..90d09542c45 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -10418,6 +10418,7 @@ syms_of_w32fns (void) | |||
| 10418 | DEFSYM (Qserif, "serif"); | 10418 | DEFSYM (Qserif, "serif"); |
| 10419 | DEFSYM (Qzlib, "zlib"); | 10419 | DEFSYM (Qzlib, "zlib"); |
| 10420 | DEFSYM (Qlcms2, "lcms2"); | 10420 | DEFSYM (Qlcms2, "lcms2"); |
| 10421 | DEFSYM (Qjson, "json"); | ||
| 10421 | 10422 | ||
| 10422 | Fput (Qundefined_color, Qerror_conditions, | 10423 | Fput (Qundefined_color, Qerror_conditions, |
| 10423 | listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror)); | 10424 | listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror)); |