New upstream version 8.1.28+dfsg
Lev Lamberov
4 years ago
105 | 105 | | `-DMULTI_THREADED=OFF` | Drop support for Prolog threads | |
106 | 106 | | `-DUSE_SIGNALS=OFF` | Drop signal support | |
107 | 107 | | `-DUSE_GMP=OFF` | Drop bignum and rational numbers | |
108 | | `-DUSE_TCMALLOC=OFF` | Do not link against `-ltcmalloc` | | |
108 | 109 | | `-DSWIPL_SHARED_LIB=OFF` | Build Prolog kernel as static lib | |
109 | 110 | | `-DSWIPL_INSTALL_IN_LIB=ON` | Install libswipl.so in <prefix>/lib | |
111 | | `-DSWIPL_INSTALL_IN_SHARE=ON` | Install docs in <prefix>/share | | |
110 | 112 | | `-DSWIPL_M32=ON` | Make 32-bit version on 64-bit Linux | |
111 | 113 | | `-DSWIPL_PACKAGES=OFF` | Only build the core system | |
112 | 114 | | `-DSWIPL_PACKAGES_BASIC=OFF` | Drop all basic packages | |
334 | 336 | % ninja |
335 | 337 | |
336 | 338 | See also `cmake/BuildType.cmake` and `PL_halt()` in `src/pl-fli.c`. |
339 | ||
340 | You can run the tests normally using `ctest`. Note that the `swipl:GC` | |
341 | test requires more stack than the default when using AddressSanitizer. | |
342 | To fix this run (bash) `ulimit -s 20000` before running `ctest`. The | |
343 | test `jpl:prolog_in_java` because Java is not loaded with | |
344 | AddressSanitizer preloaded. All other tests should pass (about 4 times | |
345 | slower than normal). | |
337 | 346 | |
338 | 347 | |
339 | 348 | ## Packaging |
14 | 14 | option(USE_GMP |
15 | 15 | "Use GNU MP Bignum library (GPL)" |
16 | 16 | ON) |
17 | option(USE_TCMALLOC | |
18 | "Use Google tcmalloc instead of default malloc" | |
19 | ON) | |
17 | 20 | option(SWIPL_SHARED_LIB |
18 | 21 | "Put kernel in a shared library" |
19 | 22 | ON) |
22 | 25 | OFF) |
23 | 26 | option(SWIPL_INSTALL_IN_LIB |
24 | 27 | "Install library in ${CMAKE_INSTALL_PREFIX}/lib" |
28 | OFF) | |
29 | option(SWIPL_INSTALL_IN_SHARE | |
30 | "Install docs in ${CMAKE_INSTALL_PREFIX}/share/swipl" | |
25 | 31 | OFF) |
26 | 32 | option(SWIPL_M32 |
27 | 33 | "Build 32-bit version on 64-bit Linux using multilib and gcc -m32" |
109 | 115 | set(SWIPL_INSTALL_RESOURCES SWI-Prolog.app/Contents/Resources) |
110 | 116 | else() |
111 | 117 | set(SWIPL_INSTALL_PREFIX lib/${SWIPL_INSTALL_DIR}) |
118 | if(SWIPL_INSTALL_IN_SHARE) | |
119 | set(SWIPL_INSTALL_SHARE_PREFIX share/${SWIPL_INSTALL_DIR}) | |
120 | endif() | |
112 | 121 | set(SWIPL_INSTALL_ARCH_EXE ${SWIPL_INSTALL_PREFIX}/bin/${SWIPL_ARCH}) |
113 | 122 | set(SWIPL_INSTALL_ARCH_LIB ${SWIPL_INSTALL_PREFIX}/lib/${SWIPL_ARCH}) |
114 | 123 | set(SWIPL_INSTALL_MANPAGES share/man/man1 |
121 | 130 | |
122 | 131 | endif(WIN32) |
123 | 132 | |
133 | if(NOT SWIPL_INSTALL_SHARE_PREFIX) | |
134 | set(SWIPL_INSTALL_SHARE_PREFIX "${SWIPL_INSTALL_PREFIX}") | |
135 | endif() | |
136 | ||
124 | 137 | set(SWIPL_INSTALL_LIBRARY ${SWIPL_INSTALL_PREFIX}/library) |
125 | 138 | set(SWIPL_INSTALL_BOOT ${SWIPL_INSTALL_PREFIX}/boot) |
126 | 139 | set(SWIPL_INSTALL_INCLUDE ${SWIPL_INSTALL_PREFIX}/include) |
140 | set(SWIPL_INSTALL_DOC ${SWIPL_INSTALL_SHARE_PREFIX}/doc) | |
127 | 141 | if(INSTALL_TESTS) |
128 | 142 | set(INSTALL_TESTS_DIR ${SWIPL_INSTALL_PREFIX}/test) |
129 | 143 | endif() |
146 | 160 | if(MULTI_THREADED) |
147 | 161 | find_package(Threads) |
148 | 162 | endif() |
163 | ||
164 | include(TestLargeFiles) | |
165 | OPJ_TEST_LARGE_FILES(HAVE_LARGE_FILES) | |
149 | 166 | |
150 | 167 | set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "Core_system") |
151 | 168 | |
157 | 174 | |
158 | 175 | if(INSTALL_DOCUMENTATION) |
159 | 176 | include(Documentation) |
177 | set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Documentation) | |
178 | ||
160 | 179 | add_custom_target( |
161 | 180 | doc ALL |
162 | 181 | COMMENT "Build the documentation") |
176 | 195 | man_index |
177 | 196 | DEPENDS ${MAN_INDEX}) |
178 | 197 | add_dependencies(doc man_index) |
179 | install(FILES ${MAN_INDEX} DESTINATION ${SWIPL_INSTALL_PREFIX}/doc) | |
198 | install(FILES ${MAN_INDEX} DESTINATION ${SWIPL_INSTALL_DOC}) | |
180 | 199 | |
181 | 200 | if(BUILD_PDF_DOCUMENTATION) |
182 | 201 | add_custom_target( |
185 | 204 | add_dependencies(doc doc.pdf) |
186 | 205 | endif() |
187 | 206 | |
188 | set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Documentation) | |
189 | 207 | add_subdirectory(man) |
190 | 208 | install(FILES packages/index.html |
191 | DESTINATION ${SWIPL_INSTALL_PREFIX}/doc/packages) | |
209 | DESTINATION ${SWIPL_INSTALL_DOC}/packages) | |
192 | 210 | endif(INSTALL_DOCUMENTATION) |
193 | 211 | |
194 | 212 | # Install a prolog script to run tests on target device |
199 | 217 | set(INSTALL_TESTS_DB ${CMAKE_BINARY_DIR}/cmake_pkg_tests.db) |
200 | 218 | #Move test db to installation |
201 | 219 | install(FILES ${INSTALL_TESTS_DB} |
202 | DESTINATION ${INSTALL_TESTS_DIR}/) | |
220 | DESTINATION ${INSTALL_TESTS_DIR} | |
221 | COMPONENT Tests) | |
203 | 222 | file(REMOVE ${INSTALL_TESTS_DB}) |
204 | 223 | endif(INSTALL_TESTS) |
205 | 224 |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2017, VU University Amsterdam | |
5 | Copyright (c) 2017-2020, VU University Amsterdam | |
6 | CWI, Amsterdam | |
6 | 7 | All rights reserved. |
7 | 8 | |
8 | 9 | Redistribution and use in source and binary forms, with or without |
40 | 41 | % |
41 | 42 | % Wait for signals from other threads to perform global GC operations |
42 | 43 | % and do them for them. |
44 | % | |
45 | % When using [tcmalloc](https://github.com/google/tcmalloc) we call | |
46 | % MallocExtension_MarkThreadIdle() to transfer the collected memory | |
47 | % immediately to the other threads. | |
43 | 48 | |
44 | 49 | gc_loop :- |
45 | 50 | repeat, |
46 | '$gc_wait'(Action), | |
51 | thread_idle('$gc_wait'(Action), short), | |
47 | 52 | ( Action == abort |
48 | 53 | -> true |
49 | 54 | ; process(Action) |
928 | 928 | library_directory(Dir)). |
929 | 929 | user:file_search_path(swi, Home) :- |
930 | 930 | current_prolog_flag(home, Home). |
931 | user:file_search_path(swi, Home) :- | |
932 | current_prolog_flag(shared_home, Home). | |
931 | 933 | user:file_search_path(foreign, swi(ArchLib)) :- |
932 | 934 | \+ current_prolog_flag(windows, true), |
933 | 935 | current_prolog_flag(arch, Arch), |
3962 | 3964 | user:prolog_list_goal(Goal), |
3963 | 3965 | !. |
3964 | 3966 | '$prolog_list_goal'(Goal) :- |
3965 | user:listing(Goal). | |
3967 | use_module(library(listing), [listing/1]), | |
3968 | @(listing(Goal), user). | |
3969 | ||
3966 | 3970 | |
3967 | 3971 | /******************************* |
3968 | 3972 | * MISC * |
1940 | 1940 | !, |
1941 | 1941 | actions_to_format(T, Fmt0, Args), |
1942 | 1942 | atom_concat('~n', Fmt0, Fmt). |
1943 | actions_to_format([Skip|T], Fmt, Args) :- | |
1944 | action_skip(Skip), | |
1945 | !, | |
1946 | actions_to_format(T, Fmt, Args). | |
1947 | actions_to_format([Fmt0-Args0|Tail], Fmt, Args) :- | |
1943 | actions_to_format([ansi(_Attrs, Fmt0, Args0)|Tail], Fmt, Args) :- | |
1948 | 1944 | !, |
1949 | 1945 | actions_to_format(Tail, Fmt1, Args1), |
1950 | 1946 | atom_concat(Fmt0, Fmt1, Fmt), |
1951 | 1947 | append_args(Args0, Args1, Args). |
1948 | actions_to_format([Fmt0-Args0|Tail], Fmt, Args) :- | |
1949 | !, | |
1950 | actions_to_format(Tail, Fmt1, Args1), | |
1951 | atom_concat(Fmt0, Fmt1, Fmt), | |
1952 | append_args(Args0, Args1, Args). | |
1953 | actions_to_format([Skip|T], Fmt, Args) :- | |
1954 | action_skip(Skip), | |
1955 | !, | |
1956 | actions_to_format(T, Fmt, Args). | |
1952 | 1957 | actions_to_format([Term|Tail], Fmt, Args) :- |
1953 | 1958 | atomic(Term), |
1954 | 1959 | !, |
1961 | 1966 | |
1962 | 1967 | action_skip(at_same_line). |
1963 | 1968 | action_skip(flush). |
1964 | action_skip(ansi(_Attrs, _Fmt, _Args)). | |
1965 | 1969 | action_skip(begin(_Level, _Ctx)). |
1966 | 1970 | action_skip(end(_Ctx)). |
1967 | 1971 |
899 | 899 | '$get_predicate_attribute'(Pred, incremental, 1). |
900 | 900 | '$predicate_property'(abstract(N), Pred) :- |
901 | 901 | '$get_predicate_attribute'(Pred, abstract, N). |
902 | '$predicate_property'(size(Bytes), Pred) :- | |
903 | '$get_predicate_attribute'(Pred, size, Bytes). | |
902 | 904 | |
903 | 905 | system_undefined(user:prolog_trace_interception/4). |
904 | 906 | system_undefined(user:prolog_exception_hook/4). |
1122 | 1124 | module_property(line_count(_)). |
1123 | 1125 | module_property(exports(_)). |
1124 | 1126 | module_property(exported_operators(_)). |
1127 | module_property(size(_)). | |
1125 | 1128 | module_property(program_size(_)). |
1126 | 1129 | module_property(program_space(_)). |
1127 | 1130 | module_property(last_modified_generation(_)). |
1215 | 1218 | trie_property(reevaluated(_)). |
1216 | 1219 | trie_property(deadlock(_)). % Shared tabling stats |
1217 | 1220 | trie_property(wait(_)). |
1221 | trie_property(idg_affected_count(_)). | |
1222 | trie_property(idg_dependent_count(_)). | |
1223 | trie_property(idg_size(_)). | |
1218 | 1224 | |
1219 | 1225 | |
1220 | 1226 | /******************************** |
50 | 50 | check_include_file(zlib.h HAVE_ZLIB_H) |
51 | 51 | check_include_file(crt_externs.h HAVE_CRT_EXTERNS_H) |
52 | 52 | |
53 | check_library_exists(dl dlopen "" HAVE_LIBDL) | |
54 | check_library_exists(m sin "" HAVE_LIBM) | |
55 | check_library_exists(rt clock_gettime "" HAVE_LIBRT) | |
53 | check_c_source_compiles( | |
54 | "int val = 1; | |
55 | int main() { __atomic_add_fetch(&val, 2, __ATOMIC_SEQ_CST); }" | |
56 | HAVE_GCC_ATOMIC) | |
57 | check_c_source_compiles( | |
58 | "#include <stdint.h> | |
59 | uint64_t val = 1; | |
60 | int main() { __atomic_add_fetch(&val, 2, __ATOMIC_SEQ_CST); }" | |
61 | HAVE_GCC_ATOMIC_8) | |
62 | if(HAVE_GCC_ATOMIC AND NOT HAVE_GCC_ATOMIC_8) | |
63 | check_library_exists(atomic __atomic_add_fetch_4 "" HAVE_LIBATOMIC) | |
64 | else() | |
65 | set(HAVE_LIBATOMIC OFF CACHE BOOL "No need to link with -latomic") | |
66 | endif() | |
67 | ||
68 | check_library_exists(dl dlopen "" HAVE_LIBDL) | |
69 | check_library_exists(m sin "" HAVE_LIBM) | |
70 | check_library_exists(rt clock_gettime "" HAVE_LIBRT) | |
56 | 71 | |
57 | 72 | if(HAVE_LIBDL) |
58 | 73 | set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl) |
4 | 4 | if(UNIX AND NOT EMSCRIPTEN) |
5 | 5 | find_package(Curses) |
6 | 6 | endif() |
7 | if(USE_TCMALLOC) | |
8 | find_package(LibTCMalloc) | |
9 | endif() |
0 | # - Try to find Google LibTCMalloc | |
1 | # Once done this will define | |
2 | # LIBTCMALLOC_FOUND - System has tcmalloc (minimal) | |
3 | # LIBTCMALLOC_LIBRARIES - The libraries needed to use tcmalloc | |
4 | # LIBTCMALLOC_DEFINITIONS - Compiler switches required for using tcmalloc | |
5 | ||
6 | find_package(PkgConfig) | |
7 | pkg_check_modules(PC_LIBTCMALLOC_MINIMAL QUIET libtcmalloc_minimal) | |
8 | set(LIBTCMALLOC_DEFINITIONS ${PC_LIBTCMALLOC_MINIMAL_CFLAGS_OTHER}) | |
9 | ||
10 | find_library(LIBTCMALLOC_LIBRARY NAMES tcmalloc_minimal | |
11 | HINTS ${PC_LIBTCMALLOC_MINIMAL_LIBDIR} | |
12 | ${PC_LIBTCMALLOC_MINIMAL_LIBRARY_DIRS} ) | |
13 | ||
14 | include(FindPackageHandleStandardArgs) | |
15 | # handle the QUIETLY and REQUIRED arguments and set LIBTCMALLOC_FOUND to TRUE | |
16 | # if all listed variables are TRUE | |
17 | find_package_handle_standard_args(LibTCMalloc DEFAULT_MSG | |
18 | LIBTCMALLOC_LIBRARY) | |
19 | ||
20 | mark_as_advanced(LIBTCMALLOC_LIBRARY ) | |
21 | ||
22 | set(LIBTCMALLOC_LIBRARIES ${LIBTCMALLOC_LIBRARY} ) |
5 | 5 | check_c_source_compiles( |
6 | 6 | "unsigned int x = 11; int main() { return __builtin_popcount(x); }" |
7 | 7 | HAVE__BUILTIN_POPCOUNT) |
8 | check_c_source_compiles( | |
9 | "int main() { __sync_synchronize(); return 0;}" | |
10 | HAVE__SYNC_SYNCHRONIZE) | |
11 | check_c_source_compiles( | |
12 | "long long v = 1; int main() { return __sync_add_and_fetch(&v, 1); }" | |
13 | HAVE___SYNC_ADD_AND_FETCH_8) | |
14 | 8 | check_c_source_compiles( |
15 | 9 | "int i=0; int main() { return __builtin_expect(i, 0) ? 0 : 1; }" |
16 | 10 | HAVE___BUILTIN_EXPECT) |
78 | 78 | endif() |
79 | 79 | endfunction() |
80 | 80 | |
81 | # install_in_home(name ...) | |
82 | # | |
83 | # Install the targets in the local home. This replaces | |
84 | # SWIPL_INSTALL_PREFIX or SWIPL_INSTALL_SHARE_PREFIX by `home` | |
85 | ||
81 | 86 | function(install_in_home name) |
82 | 87 | cmake_parse_arguments(my "" "RENAME;DESTINATION" "FILES" ${ARGN}) |
83 | 88 | if(my_DESTINATION AND my_FILES) |
85 | 90 | string(REGEX REPLACE |
86 | 91 | "^${pattern}" |
87 | 92 | "${SWIPL_BUILD_HOME}" buildhome ${my_DESTINATION}) |
93 | ||
94 | if(buildhome STREQUAL my_DESTINATION AND | |
95 | NOT SWIPL_INSTALL_PREFIX STREQUAL SWIPL_INSTALL_SHARE_PREFIX) | |
96 | string(REPLACE "." "\\." pattern ${SWIPL_INSTALL_SHARE_PREFIX}) | |
97 | string(REGEX REPLACE | |
98 | "^${pattern}" | |
99 | "${SWIPL_BUILD_HOME}" buildhome ${my_DESTINATION}) | |
100 | endif() | |
88 | 101 | |
89 | 102 | set(deps) |
90 | 103 |
7 | 7 | set(C_CXX ${CMAKE_CXX_COMPILER}) |
8 | 8 | endif() |
9 | 9 | set(PLHOME ${CMAKE_INSTALL_PREFIX}/${SWIPL_INSTALL_PREFIX}) |
10 | if(SWIPL_INSTALL_IN_SHARE) | |
11 | set(PLSHAREDHOME ${CMAKE_INSTALL_PREFIX}/share/${SWIPL_INSTALL_DIR}) | |
12 | endif() | |
10 | 13 | set(PLARCH ${SWIPL_ARCH}) |
11 | 14 | string(REGEX REPLACE "\\." "" SO_EXT "${CMAKE_SHARED_MODULE_SUFFIX}") |
12 | 15 |
0 | #include <sys/types.h> | |
1 | ||
2 | /* Cause a compile-time error if off_t is smaller than 64 bits */ | |
3 | #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) | |
4 | int off_t_is_large[ (LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1 ]; | |
5 | ||
6 | int main(int argc, char **argv) | |
7 | { | |
8 | return 0; | |
9 | } | |
10 |
0 | #cmakedefine _LARGEFILE_SOURCE | |
1 | #cmakedefine _LARGE_FILES | |
2 | #cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@ | |
3 | ||
4 | #include <sys/types.h> | |
5 | #include <stdio.h> | |
6 | #include <stdlib.h> | |
7 | ||
8 | int main(int argc, char **argv) | |
9 | { | |
10 | /* Cause a compile-time error if off_t is smaller than 64 bits, | |
11 | * and make sure we have ftello / fseeko. | |
12 | */ | |
13 | #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) | |
14 | int off_t_is_large[ (LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1 ]; | |
15 | FILE *fp = fopen(argv[0],"r"); | |
16 | off_t offset = ftello( fp ); | |
17 | ||
18 | fseeko( fp, offset, SEEK_CUR ); | |
19 | fclose(fp); | |
20 | return 0; | |
21 | } | |
22 |
0 | # - Define macro to check large file support | |
1 | # | |
2 | # OPJ_TEST_LARGE_FILES(VARIABLE) | |
3 | # | |
4 | # VARIABLE will be set to true if off_t is 64 bits, and fseeko/ftello present. | |
5 | # This macro will also defines the necessary variable enable large file support, for instance | |
6 | # _LARGE_FILES | |
7 | # _LARGEFILE_SOURCE | |
8 | # _FILE_OFFSET_BITS 64 | |
9 | # OPJ_HAVE_FSEEKO | |
10 | # | |
11 | # However, it is YOUR job to make sure these defines are set in a #cmakedefine so they | |
12 | # end up in a config.h file that is included in your source if necessary! | |
13 | # | |
14 | # Adapted from Gromacs project (http://www.gromacs.org/) | |
15 | # by Julien Malik | |
16 | # | |
17 | ||
18 | macro(OPJ_TEST_LARGE_FILES VARIABLE) | |
19 | if(NOT DEFINED ${VARIABLE}) | |
20 | ||
21 | # On most platforms it is probably overkill to first test the flags for 64-bit off_t, | |
22 | # and then separately fseeko. However, in the future we might have 128-bit filesystems | |
23 | # (ZFS), so it might be dangerous to indiscriminately set e.g. _FILE_OFFSET_BITS=64. | |
24 | ||
25 | message(STATUS "Checking for 64-bit off_t") | |
26 | ||
27 | # First check without any special flags | |
28 | try_compile(FILE64_OK "${PROJECT_BINARY_DIR}" | |
29 | "${PROJECT_SOURCE_DIR}/cmake/TestFileOffsetBits.c") | |
30 | if(FILE64_OK) | |
31 | message(STATUS "Checking for 64-bit off_t - present") | |
32 | endif() | |
33 | ||
34 | if(NOT FILE64_OK) | |
35 | # Test with _FILE_OFFSET_BITS=64 | |
36 | try_compile(FILE64_OK "${PROJECT_BINARY_DIR}" | |
37 | "${PROJECT_SOURCE_DIR}/cmake/TestFileOffsetBits.c" | |
38 | COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64" ) | |
39 | if(FILE64_OK) | |
40 | message(STATUS "Checking for 64-bit off_t - present with _FILE_OFFSET_BITS=64") | |
41 | set(_FILE_OFFSET_BITS 64) | |
42 | endif() | |
43 | endif() | |
44 | ||
45 | if(NOT FILE64_OK) | |
46 | # Test with _LARGE_FILES | |
47 | try_compile(FILE64_OK "${PROJECT_BINARY_DIR}" | |
48 | "${PROJECT_SOURCE_DIR}/cmake/TestFileOffsetBits.c" | |
49 | COMPILE_DEFINITIONS "-D_LARGE_FILES" ) | |
50 | if(FILE64_OK) | |
51 | message(STATUS "Checking for 64-bit off_t - present with _LARGE_FILES") | |
52 | set(_LARGE_FILES 1) | |
53 | endif() | |
54 | endif() | |
55 | ||
56 | if(NOT FILE64_OK) | |
57 | # Test with _LARGEFILE_SOURCE | |
58 | try_compile(FILE64_OK "${PROJECT_BINARY_DIR}" | |
59 | "${PROJECT_SOURCE_DIR}/cmake/TestFileOffsetBits.c" | |
60 | COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE" ) | |
61 | if(FILE64_OK) | |
62 | message(STATUS "Checking for 64-bit off_t - present with _LARGEFILE_SOURCE") | |
63 | set(_LARGEFILE_SOURCE 1) | |
64 | endif() | |
65 | endif() | |
66 | ||
67 | ||
68 | #if(NOT FILE64_OK) | |
69 | # # now check for Windows stuff | |
70 | # try_compile(FILE64_OK "${PROJECT_BINARY_DIR}" | |
71 | # "${PROJECT_SOURCE_DIR}/cmake/TestWindowsFSeek.c") | |
72 | # if(FILE64_OK) | |
73 | # message(STATUS "Checking for 64-bit off_t - present with _fseeki64") | |
74 | # set(HAVE__FSEEKI64 1) | |
75 | # endif() | |
76 | #endif() | |
77 | ||
78 | if(NOT FILE64_OK) | |
79 | message(STATUS "Checking for 64-bit off_t - not present") | |
80 | endif() | |
81 | ||
82 | set(_FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} CACHE INTERNAL "Result of test for needed _FILE_OFFSET_BITS=64") | |
83 | set(_LARGE_FILES ${_LARGE_FILES} CACHE INTERNAL "Result of test for needed _LARGE_FILES") | |
84 | set(_LARGEFILE_SOURCE ${_LARGEFILE_SOURCE} CACHE INTERNAL "Result of test for needed _LARGEFILE_SOURCE") | |
85 | ||
86 | # Set the flags we might have determined to be required above | |
87 | configure_file("${PROJECT_SOURCE_DIR}/cmake/TestLargeFiles.c.cmake.in" | |
88 | "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c") | |
89 | ||
90 | message(STATUS "Checking for fseeko/ftello") | |
91 | ||
92 | # Test if ftello/fseeko are available | |
93 | try_compile(FSEEKO_COMPILE_OK | |
94 | "${PROJECT_BINARY_DIR}" | |
95 | "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c") | |
96 | ||
97 | if(FSEEKO_COMPILE_OK) | |
98 | message(STATUS "Checking for fseeko/ftello - present") | |
99 | endif() | |
100 | ||
101 | if(NOT FSEEKO_COMPILE_OK) | |
102 | # glibc 2.2 needs _LARGEFILE_SOURCE for fseeko (but not for 64-bit off_t...) | |
103 | try_compile(FSEEKO_COMPILE_OK | |
104 | "${PROJECT_BINARY_DIR}" | |
105 | "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c" | |
106 | COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE" ) | |
107 | ||
108 | if(FSEEKO_COMPILE_OK) | |
109 | message(STATUS "Checking for fseeko/ftello - present with _LARGEFILE_SOURCE") | |
110 | set(_LARGEFILE_SOURCE ${_LARGEFILE_SOURCE} CACHE INTERNAL "Result of test for needed _LARGEFILE_SOURCE") | |
111 | endif() | |
112 | endif() | |
113 | ||
114 | if(FSEEKO_COMPILE_OK) | |
115 | set(OPJ_HAVE_FSEEKO ON CACHE INTERNAL "Result of test for fseeko/ftello") | |
116 | else() | |
117 | message(STATUS "Checking for fseeko/ftello - not found") | |
118 | set(OPJ_HAVE_FSEEKO OFF CACHE INTERNAL "Result of test for fseeko/ftello") | |
119 | endif() | |
120 | ||
121 | if(FILE64_OK AND FSEEKO_COMPILE_OK) | |
122 | message(STATUS "Large File support - found") | |
123 | set(${VARIABLE} ON CACHE INTERNAL "Result of test for large file support") | |
124 | else() | |
125 | message(STATUS "Large File support - not found") | |
126 | set(${VARIABLE} OFF CACHE INTERNAL "Result of test for large file support") | |
127 | endif() | |
128 | ||
129 | endif() | |
130 | endmacro() | |
131 | ||
132 | ||
133 |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2008-2016, University of Amsterdam | |
5 | Copyright (c) 2008-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | CWI Amsterdam | |
7 | 8 | All rights reserved. |
8 | 9 | |
9 | 10 | Redistribution and use in source and binary forms, with or without |
60 | 61 | |
61 | 62 | This library provides aggregating operators over the solutions of a |
62 | 63 | predicate. The operations are a generalisation of the bagof/3, setof/3 |
63 | and findall/3 built-in predicates. The defined aggregation operations | |
64 | are counting, computing the sum, minimum, maximum, a bag of solutions | |
65 | and a set of solutions. We first give a simple example, computing the | |
66 | country with the smallest area: | |
67 | ||
68 | == | |
64 | and findall/3 built-in predicates. Aggregations that can be computed | |
65 | incrementally avoid findall/3 and run in constant memory. The defined | |
66 | aggregation operations are counting, computing the sum, minimum, | |
67 | maximum, a bag of solutions and a set of solutions. We first give a | |
68 | simple example, computing the country with the smallest area: | |
69 | ||
70 | ``` | |
69 | 71 | smallest_country(Name, Area) :- |
70 | aggregate(min(A, N), country(N, A), min(Area, Name)). | |
71 | == | |
72 | aggregate(min(A, N), country(N, A), min(Area, Name)). | |
73 | ``` | |
72 | 74 | |
73 | 75 | There are four aggregation predicates (aggregate/3, aggregate/4, aggregate_all/3 and aggregate/4), distinguished on two properties. |
74 | 76 | |
75 | 77 | $ aggregate vs. aggregate_all : |
76 | 78 | The aggregate predicates use setof/3 (aggregate/4) or bagof/3 |
77 | 79 | (aggregate/3), dealing with existential qualified variables |
78 | (Var^Goal) and providing multiple solutions for the remaining free | |
79 | variables in Goal. The aggregate_all/3 predicate uses findall/3, | |
80 | (`Var^Goal`) and providing multiple solutions for the remaining free | |
81 | variables in `Goal`. The aggregate_all/3 predicate uses findall/3, | |
80 | 82 | implicitly qualifying all free variables and providing exactly one |
81 | 83 | solution, while aggregate_all/4 uses sort/2 over solutions that |
82 | 84 | Discriminator (see below) generated using findall/3. |
163 | 165 | |
164 | 166 | %! aggregate_all(+Template, :Goal, -Result) is semidet. |
165 | 167 | % |
166 | % Aggregate bindings in Goal according to Template. The | |
167 | % aggregate_all/3 version performs findall/3 on Goal. Note that | |
168 | % this predicate fails if Template contains one or more of min(X), | |
169 | % max(X), min(X,Witness) or max(X,Witness) and Goal has no | |
170 | % solutions, i.e., the minumum and maximum of an empty set is | |
171 | % undefined. | |
168 | % Aggregate bindings in Goal according to Template. The | |
169 | % aggregate_all/3 version performs findall/3 on Goal. Note that this | |
170 | % predicate fails if Template contains one or more of min(X), max(X), | |
171 | % min(X,Witness) or max(X,Witness) and Goal has no solutions, i.e., | |
172 | % the minimum and maximum of an empty set is undefined. | |
173 | % | |
174 | % The Template values `count`, sum(X), max(X), min(X), max(X,W) and | |
175 | % min(X,W) are processed incrementally rather than using findall/3 and | |
176 | % run in constant memory. | |
172 | 177 | |
173 | 178 | aggregate_all(Var, _, _) :- |
174 | 179 | var(Var), |
39 | 39 | list_undefined/1, % +Options |
40 | 40 | list_autoload/0, % list predicates that need autoloading |
41 | 41 | list_redefined/0, % list redefinitions |
42 | list_cross_module_calls/0, % List Module:Goal usage | |
43 | list_cross_module_calls/1, % +Options | |
42 | 44 | list_void_declarations/0, % list declarations with no clauses |
43 | 45 | list_trivial_fails/0, % list goals that trivially fail |
44 | 46 | list_trivial_fails/1, % +Options |
294 | 296 | |
295 | 297 | global_module(user). |
296 | 298 | global_module(system). |
299 | ||
300 | %! list_cross_module_calls is det. | |
301 | % | |
302 | % List calls from one module to another using Module:Goal where the | |
303 | % callee is not defined exported, public or multifile, i.e., where the | |
304 | % callee should be considered _private_. | |
305 | ||
306 | list_cross_module_calls :- | |
307 | list_cross_module_calls([]). | |
308 | ||
309 | list_cross_module_calls(Options) :- | |
310 | call_cleanup( | |
311 | list_cross_module_calls_guarded(Options), | |
312 | retractall(cross_module_call(_,_,_))). | |
313 | ||
314 | list_cross_module_calls_guarded(Options) :- | |
315 | merge_options(Options, | |
316 | [ module_class([user]) | |
317 | ], | |
318 | WalkOptions), | |
319 | prolog_walk_code([ trace_reference(_), | |
320 | trace_condition(cross_module_call), | |
321 | on_trace(write_call) | |
322 | | WalkOptions | |
323 | ]). | |
324 | ||
325 | :- thread_local | |
326 | cross_module_call/3. | |
327 | ||
328 | :- public | |
329 | cross_module_call/2, | |
330 | write_call/3. | |
331 | ||
332 | cross_module_call(Callee, Context) :- | |
333 | \+ same_module_call(Callee, Context). | |
334 | ||
335 | same_module_call(Callee, Context) :- | |
336 | caller_module(Context, MCaller), | |
337 | Callee = (MCallee:_), | |
338 | ( ( MCaller = MCallee | |
339 | ; predicate_property(Callee, exported) | |
340 | ; predicate_property(Callee, built_in) | |
341 | ; predicate_property(Callee, public) | |
342 | ; clause_property(Context.get(clause), module(MCallee)) | |
343 | ; predicate_property(Callee, multifile) | |
344 | ) | |
345 | -> true | |
346 | ). | |
347 | ||
348 | caller_module(Context, MCaller) :- | |
349 | Caller = Context.caller, | |
350 | ( Caller = (MCaller:_) | |
351 | -> true | |
352 | ; Caller == '<initialization>', | |
353 | MCaller = Context.module | |
354 | ). | |
355 | ||
356 | write_call(Callee, Caller, Position) :- | |
357 | cross_module_call(Callee, Caller, Position), | |
358 | !. | |
359 | write_call(Callee, Caller, Position) :- | |
360 | ( cross_module_call(_,_,_) | |
361 | -> true | |
362 | ; print_message(warning, check(cross_module_calls)) | |
363 | ), | |
364 | asserta(cross_module_call(Callee, Caller, Position)), | |
365 | print_message(warning, | |
366 | check(cross_module_call(Callee, Caller, Position))). | |
297 | 367 | |
298 | 368 | %! list_void_declarations is det. |
299 | 369 | % |
808 | 878 | prolog:message(check(redefined(In, From, Pred))) --> |
809 | 879 | predicate(In:Pred), |
810 | 880 | redefined(In, From). |
881 | prolog:message(check(cross_module_calls)) --> | |
882 | [ 'Qualified calls to private predicates'-[] ]. | |
883 | prolog:message(check(cross_module_call(Callee, _Caller, Location))) --> | |
884 | { pi_head(PI, Callee) }, | |
885 | [ ' '-[] ], | |
886 | '$messages':swi_location(Location), | |
887 | [ 'Cross-module call to ~p'-[PI] ]. | |
811 | 888 | prolog:message(check(trivial_failures)) --> |
812 | 889 | [ 'The following goals fail because there are no matching clauses.' ]. |
813 | 890 | prolog:message(check(trivial_failure(Goal, Refs))) --> |
80 | 80 | % features. |
81 | 81 | |
82 | 82 | % Feature tests |
83 | component(tcmalloc, | |
84 | _{ test:test_tcmalloc, | |
85 | url:'tcmalloc.html' | |
86 | }). | |
83 | 87 | component(gmp, |
84 | 88 | _{ test:current_prolog_flag(bounded, false), |
85 | 89 | url:'gmp.html' |
311 | 315 | * SPECIAL TESTS * |
312 | 316 | *******************************/ |
313 | 317 | |
318 | %! test_tcmalloc | |
319 | ||
320 | :- if(current_predicate(malloc_property/1)). | |
321 | test_tcmalloc :- | |
322 | malloc_property('generic.current_allocated_bytes'(Bytes)), | |
323 | Bytes > 1 000 000. | |
324 | :- else. | |
325 | test_tcmalloc :- | |
326 | fail. | |
327 | :- endif. | |
328 | ||
314 | 329 | %! archive_features |
315 | 330 | % |
316 | 331 | % Report features supported by library(archive). |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2006-2018, University of Amsterdam | |
5 | Copyright (c) 2006-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
334 | 334 | % True if Term satisfies Type. |
335 | 335 | |
336 | 336 | :- '$clausable'(has_type/2). % always allow clause/2 |
337 | :- public % May be called through current_type/3 | |
338 | is_list_or_partial_list/1, | |
339 | current_encoding/1, | |
340 | element_types/2. | |
337 | 341 | |
338 | 342 | has_type(any, _). |
339 | 343 | has_type(atom, X) :- atom(X). |
98 | 98 | test,development]))), |
99 | 99 | source(boolean), |
100 | 100 | trace_reference(any), |
101 | trace_condition(callable), | |
101 | 102 | on_trace(callable), |
102 | 103 | infer_meta_predicates(oneof([false,true,all])), |
103 | 104 | evaluate(boolean), |
114 | 115 | infer_meta_predicates:oneof([false,true,all])=true, |
115 | 116 | clauses:list, % Walk only these clauses |
116 | 117 | trace_reference:any=(-), |
118 | trace_condition:callable, % Call-back condition | |
117 | 119 | on_trace:callable, % Call-back on trace hits |
118 | 120 | % private stuff |
119 | 121 | clause, % Processed clause |
174 | 176 | % Print all calls to goals that subsume Callable. Goals are |
175 | 177 | % represented as Module:Callable (i.e., they are always |
176 | 178 | % qualified). See also subsumes_term/2. |
179 | % | |
180 | % * trace_condition(:Cond) | |
181 | % Additional filter condition applied after `trace_reference`. | |
182 | % Called as call(Cond, Callee, Context), where `Context` is a | |
183 | % dict containing the following keys: | |
184 | % | |
185 | % - Context:caller | |
186 | % Qualified term representing the caller or the atom | |
187 | % '<initialization>'. | |
188 | % - Context:module | |
189 | % Module being processed | |
190 | % - Context:clause | |
191 | % If we are processing a normal clause, the clause reference | |
192 | % to this clause. | |
193 | % - Context:initialization | |
194 | % If we are processing an initialization/1 directive, a term | |
195 | % `File:Line` representing the location of the declaration. | |
177 | 196 | % |
178 | 197 | % * on_trace(:OnTrace) |
179 | 198 | % If a reference to =trace_reference= is found, call |
234 | 253 | ). |
235 | 254 | |
236 | 255 | is_meta(on_trace). |
237 | ||
256 | is_meta(trace_condition). | |
238 | 257 | |
239 | 258 | %! walk_clauses(+Clauses, +OTerm) is det. |
240 | 259 | % |
290 | 309 | ; walk_option_module_class(OTerm, Classes), |
291 | 310 | source_file_property(File, module(MF)) |
292 | 311 | -> module_property(MF, class(Class)), |
293 | memberchk(Class, Classes) | |
312 | memberchk(Class, Classes), | |
313 | walk_option_module(OTerm, MF) | |
294 | 314 | ; true |
295 | 315 | ). |
296 | 316 | |
308 | 328 | |
309 | 329 | find_walk_from_module(M, OTerm) :- |
310 | 330 | debug(autoload, 'Analysing module ~q', [M]), |
331 | walk_option_module(OTerm, M), | |
311 | 332 | forall(predicate_in_module(M, PI), |
312 | 333 | walk_called_by_pred(M:PI, OTerm)). |
313 | 334 | |
511 | 532 | ; predicate_property(Module:Goal, imported_from(M2)), |
512 | 533 | subsumes_term(To, M2:Goal) |
513 | 534 | ), |
535 | trace_condition(M2:Goal, TermPos, OTerm), | |
514 | 536 | print_reference(M2:Goal, TermPos, trace, OTerm), |
515 | 537 | fail. % Continue search |
516 | 538 | walk_called(Goal, Module, _, OTerm) :- |
564 | 586 | undefined(Module:Goal, TermPos, OTerm). |
565 | 587 | walk_called(Goal, _Module, TermPos, OTerm) :- |
566 | 588 | not_callable(Goal, TermPos, OTerm). |
589 | ||
590 | %! trace_condition(:Callee, +TermPos, +OTerm) is semidet. | |
591 | % | |
592 | % Call call(Condition, Callee, Dict) | |
593 | ||
594 | trace_condition(Callee, TermPos, OTerm) :- | |
595 | walk_option_trace_condition(OTerm, Cond), nonvar(Cond), | |
596 | !, | |
597 | cond_location_context(OTerm, TermPos, Context0), | |
598 | walk_option_caller(OTerm, Caller), | |
599 | walk_option_module(OTerm, Module), | |
600 | put_dict(#{caller:Caller, module:Module}, Context0, Context), | |
601 | call(Cond, Callee, Context). | |
602 | trace_condition(_, _, _). | |
603 | ||
604 | cond_location_context(OTerm, _TermPos, Context) :- | |
605 | walk_option_clause(OTerm, Clause), nonvar(Clause), | |
606 | !, | |
607 | Context = #{clause:Clause}. | |
608 | cond_location_context(OTerm, _TermPos, Context) :- | |
609 | walk_option_initialization(OTerm, Init), nonvar(Init), | |
610 | !, | |
611 | Context = #{initialization:Init}. | |
567 | 612 | |
568 | 613 | %! undecided(+Variable, +TermPos, +OTerm) |
569 | 614 | |
891 | 936 | :- meta_predicate |
892 | 937 | subterm_pos(+, +, 2, +, -), |
893 | 938 | sublist_pos(+, +, +, +, 2, -). |
939 | :- public | |
940 | subterm_pos/5. % used in library(check). | |
894 | 941 | |
895 | 942 | subterm_pos(_, _, _, Pos, _) :- |
896 | 943 | var(Pos), !, fail. |
1250 | 1250 | xref_meta(thread_create(A,_,_), [A]). |
1251 | 1251 | xref_meta(thread_create(A,_), [A]). |
1252 | 1252 | xref_meta(thread_signal(_,A), [A]). |
1253 | xref_meta(thread_idle(A,_), [A]). | |
1253 | 1254 | xref_meta(thread_at_exit(A), [A]). |
1254 | 1255 | xref_meta(thread_initialization(A), [A]). |
1255 | 1256 | xref_meta(engine_create(_,A,_), [A]). |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2013-2019, VU University Amsterdam | |
5 | Copyright (c) 2013-2020, VU University Amsterdam | |
6 | 6 | CWI, Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
36 | 36 | [ safe_goal/1, % :Goal |
37 | 37 | safe_call/1 % :Goal |
38 | 38 | ]). |
39 | :- autoload(library(apply),[maplist/2]). | |
40 | :- autoload(library(assoc),[empty_assoc/1,get_assoc/3,put_assoc/4]). | |
41 | :- autoload(library(debug),[debug/3,debugging/1]). | |
42 | :- autoload(library(error), | |
43 | [ must_be/2, | |
44 | instantiation_error/1, | |
45 | type_error/2, | |
46 | permission_error/3 | |
47 | ]). | |
48 | :- autoload(library(lists),[append/3]). | |
49 | :- autoload(library(prolog_format),[format_types/2]). | |
50 | 39 | :- use_module(library(apply_macros),[expand_phrase/2]). |
51 | ||
40 | :- use_module(library(apply),[maplist/2]). | |
41 | :- use_module(library(assoc),[empty_assoc/1,get_assoc/3,put_assoc/4]). | |
42 | :- use_module(library(debug),[debug/3,debugging/1]). | |
43 | :- use_module(library(error), | |
44 | [ must_be/2, | |
45 | instantiation_error/1, | |
46 | type_error/2, | |
47 | permission_error/3 | |
48 | ]). | |
49 | :- use_module(library(lists),[append/3]). | |
50 | :- use_module(library(prolog_format),[format_types/2]). | |
52 | 51 | |
53 | 52 | :- multifile |
54 | 53 | safe_primitive/1, % Goal |
133 | 133 | set(PLDOC_LIB ${PLDOC_LIB} PARENT_SCOPE) |
134 | 134 | endfunction() |
135 | 135 | |
136 | has_package(ssl, HAVE_SSL_PACKAGE) | |
137 | if(HAVE_SSL_PACKAGE) | |
138 | set(doc_depends_ssl ssl) | |
139 | endif() | |
140 | ||
136 | 141 | # Specify how to generate tex files from PlDoc |
137 | 142 | # NOTE: all files must be included from lib/library.doc and |
138 | 143 | # NOTE: lib/libsummary.doc |
146 | 151 | libdoc(pure_input --subsection) |
147 | 152 | libdoc(explain --subsection) |
148 | 153 | pldoc(lib/prologpack.tex "library(prolog_pack)" |
149 | OPTIONS --section) | |
154 | OPTIONS --section DEPENDS ${doc_depends_ssl}) | |
150 | 155 | pldoc(lib/assoclib.tex lib/assoclib.md |
151 | 156 | OPTIONS --lib=assoc --module=assoc |
152 | 157 | DEPENDS lib/assoclib.md ../library/assoc.pl) |
299 | 304 | endif() |
300 | 305 | |
301 | 306 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Manual |
302 | DESTINATION ${SWIPL_INSTALL_PREFIX}/doc) | |
307 | DESTINATION ${SWIPL_INSTALL_DOC}) | |
303 | 308 | endif(INSTALL_DOCUMENTATION) |
1590 | 1590 | \begin{description} |
1591 | 1591 | \predicate[ISO]{var}{1}{@Term} |
1592 | 1592 | True if \arg{Term} currently is a free variable. |
1593 | ||
1593 | 1594 | \predicate[ISO]{nonvar}{1}{@Term} |
1594 | 1595 | True if \arg{Term} currently is not a free variable. |
1596 | ||
1595 | 1597 | \predicate[ISO]{integer}{1}{@Term} |
1596 | 1598 | True if \arg{Term} is bound to an integer. |
1599 | ||
1597 | 1600 | \predicate[ISO]{float}{1}{@Term} |
1598 | 1601 | True if \arg{Term} is bound to a floating point number. |
1602 | ||
1599 | 1603 | \predicate{rational}{1}{@Term} |
1600 | 1604 | True if \arg{Term} is bound to a rational number. Rational numbers |
1601 | 1605 | include integers. |
1606 | ||
1602 | 1607 | \predicate{rational}{3}{@Term, -Numerator, -Denominator} |
1603 | 1608 | True if \arg{Term} is a rational number with given \arg{Numerator} and |
1604 | 1609 | \arg{Denominator}. The \arg{Numerator} and \arg{Denominator} are in |
1605 | 1610 | canonical form, which means \arg{Denominator} is a positive integer and |
1606 | 1611 | there are no common divisors between \arg{Numerator} and \arg{Denominator}. |
1612 | ||
1607 | 1613 | \predicate[ISO]{number}{1}{@Term} |
1608 | True if \arg{Term} is bound to an integer or floating point number.% | |
1609 | \footnote{As rational numbers are not atomic in the current | |
1610 | implementation and we do not want to break the rule | |
1611 | that number/1 implies atomic/1, number/1 fails on | |
1612 | rational numbers. This will change if rational numbers | |
1613 | become atomic.} | |
1614 | True if \arg{Term} is bound to a rational number (including integers) or | |
1615 | a floating point number. | |
1614 | 1616 | |
1615 | 1617 | \predicate[ISO]{atom}{1}{@Term} |
1616 | 1618 | True if \arg{Term} is bound to an atom. |
3497 | 3499 | by trie_gen_compiled/2,3. |
3498 | 3500 | \termitem{hashed}{-Count} |
3499 | 3501 | Number of nodes that use a hashed index to its children. |
3502 | \termitem{lookup_count}{-Count} | |
3503 | Number of trie_lookup/3 calls (only when compiled with | |
3504 | \const{O_TRIE_STATS}). | |
3505 | \termitem{gen_call_count}{-Count} | |
3506 | Number of trie_gen/3 calls (only when compiled with | |
3507 | \const{O_TRIE_STATS}). | |
3508 | \termitem{wait}{-Count} | |
3509 | Number of times a thread waited on this trie for another | |
3510 | thread to complete it (shared tabling, only when compiled with | |
3511 | \const{O_TRIE_STATS}). | |
3512 | \termitem{deadlock}{-Count} | |
3513 | Number of times this trie was part of a deadlock and its completion | |
3514 | was abandonned (shared tabling, only when compiled with | |
3515 | \const{O_TRIE_STATS}). | |
3516 | \end{description} | |
3517 | ||
3518 | In addition, a number of additional properties are defined on | |
3519 | \jargon{answer tries}. | |
3520 | ||
3521 | \begin{description} | |
3522 | \termitem{invalidated}{-Count} | |
3523 | Number of times the trie was invalidated (incremental tabling). | |
3524 | \termitem{reevaluated}{-Count} | |
3525 | Number of times the trie was re-evaluated (incremental tabling). | |
3526 | \termitem{idg_affected_count}{-Count} | |
3527 | Number of answer tries affected by this one (incremental tabling). | |
3528 | \termitem{idg_dependent_count}{-Count} | |
3529 | Number of answer tries this one depends on (incremental tabling). | |
3530 | \termitem{idg_size}{-Bytes} | |
3531 | Number of bytes in the IDG node representation. | |
3500 | 3532 | \end{description} |
3501 | 3533 | \end{description} |
3502 | 3534 | |
4019 | 4051 | \termitem{quasi_quotation_syntax}{} |
4020 | 4052 | The predicate (with arity~4) is declared to provide quasi quotation |
4021 | 4053 | syntax with quasi_quotation_syntax/1. |
4054 | ||
4055 | \termitem{size}{Bytes} | |
4056 | Memory used for this predicate. This includes the memory of the | |
4057 | predicate header, the combined memory of all clauses including erased | |
4058 | but not yet garbage collected clauses (see garbage_collect_clauses/0 and | |
4059 | clause_property/2) and the memory used by clause indexes (see the | |
4060 | \term{indexed}{Indexes} property. \emph{Excluded} are \jargon{lingering} | |
4061 | data structures. These are garbage data structures that have been | |
4062 | detached from the predicate but cannot yet be reclaimed because | |
4063 | they may be in use by some thread. | |
4022 | 4064 | |
4023 | 4065 | \termitem{static}{} |
4024 | 4066 | The definition can \emph{not} be modified using assertz/1 and friends. |
9989 | 10031 | agc_gained & Number of atoms removed \\ |
9990 | 10032 | agc_time & Time spent in atom garbage collections \\ |
9991 | 10033 | atoms & Total number of defined atoms \\ |
10034 | atom_space & Bytes used to represent atoms \\ | |
9992 | 10035 | c_stack & System (C-) stack limit. 0 if not known. \\ |
9993 | 10036 | cgc & Number of clause garbage collections performed \\ |
9994 | 10037 | cgc_gained & Number of clauses reclaimed \\ |
9998 | 10041 | cputime & (User) {\sc cpu} time since thread was started in seconds \\ |
9999 | 10042 | epoch & Time stamp when thread was started \\ |
10000 | 10043 | functors & Total number of defined name/arity pairs \\ |
10044 | functor_space & Bytes used to represent functors \\ | |
10001 | 10045 | global & Allocated size of the global stack in bytes \\ |
10002 | 10046 | globalused & Number of bytes in use on the global stack \\ |
10003 | 10047 | globallimit & Size to which the global stack is allowed to grow \\ |
10031 | 10075 | threads_created & MT-version: number of created threads \\ |
10032 | 10076 | engines & MT-version: number of existing engines \\ |
10033 | 10077 | engines_created & MT-version: number of created engines \\ |
10078 | threads_peak & MT-version: highest id handed out. This is a fair but | |
10079 | possibly not 100\% accurate value for the highest | |
10080 | number of threads since the process was created. \\ | |
10034 | 10081 | \hline |
10035 | 10082 | \end{tabular} |
10036 | 10083 | \end{center} |
10060 | 10107 | (Used is based on \const{ru_idrss} from getrusage(). |
10061 | 10108 | Free is based on \const{RLIMIT_DATA} from |
10062 | 10109 | getrlimit(). Both are reported as zero if the OS |
10063 | lacks support.) \\ | |
10110 | lacks support. Free is -1 if getrlimit() is supported | |
10111 | but returns infinity.) \\ | |
10064 | 10112 | stacks & [ global use, local use ] \\ |
10065 | program & [ heap, 0 ] \\ | |
10113 | program & [ heap use, 0 ] \\ | |
10066 | 10114 | global_stack & [ global use, global free ] \\ |
10067 | 10115 | local_stack & [ local use, local free ] \\ |
10068 | 10116 | trail & [ trail use, trail free ] \\ |
10112 | 10160 | |
10113 | 10161 | \section{Memory Management} \label{sec:memory} |
10114 | 10162 | |
10163 | \subsection{Garbage collection} \label{sec:gc} | |
10164 | ||
10115 | 10165 | \begin{description} |
10116 | 10166 | \predicate{garbage_collect}{0}{} |
10117 | 10167 | Invoke the global and trail stack garbage collector. Normally the |
10224 | 10274 | |
10225 | 10275 | The total space limit for all stacks is controlled using the prolog |
10226 | 10276 | flag \prologflag{stack_limit}. |
10277 | ||
10278 | \subsection{Heap memory (malloc)} \label{sec:malloc} | |
10279 | ||
10280 | \index{tcmalloc}% | |
10281 | SWI-Prolog's memory management is based on the C runtime malloc() | |
10282 | function and related functions. The characteristics of the malloc() | |
10283 | implementation may affect performance and overall memory usage of the | |
10284 | system. For most Prolog programs the performance impact of the allocator | |
10285 | is small.\footnote{Multi-threaded applications may suffer from | |
10286 | allocators that do not effectively avoid \jargon{false sharing} that | |
10287 | affect CPU cache behaviour or operate using a single lock to provide | |
10288 | thread safety. Such allocators should be rare in modern OSes.} The | |
10289 | impact on total memory usage can be significant though, in particular | |
10290 | for multi-threaded applications. This is due to two aspects of | |
10291 | SWI-Prolog memory management: | |
10292 | ||
10293 | \begin{itemize} | |
10294 | \item The Prolog stacks are allocated using malloc(). The stacks can | |
10295 | be extremely large. SWI-Prolog assumes malloc() will use a mechanism | |
10296 | that allows returning this memory to the OS. Most todays allocators | |
10297 | satisfy this requirement. | |
10298 | ||
10299 | \item Atoms and clauses are allocated by the thread that requires | |
10300 | them, but this memory is freed by the thread running the atom or | |
10301 | clause garbage collector (see garbage_collect_atoms/0 and | |
10302 | garbage_collect_clauses/0). Normally these run in the thread | |
10303 | \const{gc}, which means that all deallocation happens in this | |
10304 | thread. Notably the \href{http://www.malloc.de/en/}{ptmalloc} | |
10305 | implementation used by the GNU C library (glibc) seems to handle | |
10306 | this poorly. | |
10307 | \end{itemize} | |
10308 | ||
10309 | Starting with version 8.1.27, SWI-Prolog by default links against | |
10310 | \href{https://github.com/google/tcmalloc}{tcmalloc} when available. Note | |
10311 | that changing the allocator can only be done by linking the main | |
10312 | executable (\program{swipl}) to an alternative library. When embedded | |
10313 | (see \secref{embedded}) the main program that embeds \file{libswipl} | |
10314 | must be linked with tcmalloc. On ELF based systems (Linux), this effect | |
10315 | can also be achieved using the environment variable \const{LD_PRELOAD}: | |
10316 | ||
10317 | \begin{code} | |
10318 | % LD_PRELOAD=/path/to/libtcmalloc.so swipl ... | |
10319 | \end{code} | |
10320 | ||
10321 | If SWI-Prolog core detects that tcmalloc is the current allocator and | |
10322 | provides the following additional predicates. | |
10323 | ||
10324 | \begin{description} | |
10325 | \predicate[nondet]{malloc_property}{1}{?Property} | |
10326 | True when \arg{Property} is a property of the current allocator. The | |
10327 | properties are defined by the allocator. The properties of tcmalloc | |
10328 | are defined in | |
10329 | \file{gperftools/malloc_extension.h}:\footnote{Documentation copied from | |
10330 | the header.} | |
10331 | ||
10332 | \begin{description} | |
10333 | \termitem{'generic.current_allocated_bytes'}{-Int} | |
10334 | Number of bytes currently allocated by application. | |
10335 | \termitem{'generic.heap_size'}{-Int} | |
10336 | Number of bytes in the heap (= current_allocated_bytes + fragmentation | |
10337 | + freed memory regions). | |
10338 | \termitem{'tcmalloc.max_total_thread_cache_bytes'}{-Int} | |
10339 | Upper limit on total number of bytes stored across allper-thread caches. | |
10340 | \termitem{'tcmalloc.current_total_thread_cache_bytes'}{-Int} | |
10341 | Number of bytes used across all thread caches. | |
10342 | \termitem{'tcmalloc.central_cache_free_bytes'}{-Int} | |
10343 | Number of free bytes in the central cache that have been | |
10344 | assigned to size classes. They always count towards virtual | |
10345 | memory usage, and unless the underlying memory is swapped out | |
10346 | by the OS, they also count towards physical memory usage. | |
10347 | \termitem{'tcmalloc.transfer_cache_free_bytes'}{-Int} | |
10348 | Number of free bytes that are waiting to be transfered between | |
10349 | the central cache and a thread cache. They always count | |
10350 | towards virtual memory usage, and unless the underlying memory | |
10351 | is swapped out by the OS, they also count towards physical | |
10352 | \termitem{'tcmalloc.thread_cache_free_bytes'}{-Int} | |
10353 | Number of free bytes in thread caches. They always count | |
10354 | towards virtual memory usage, and unless the underlying memory | |
10355 | is swapped out by the OS, they also count towards physical | |
10356 | memory usage. | |
10357 | \termitem{'tcmalloc.pageheap_free_bytes'}{-Int} | |
10358 | Number of bytes in free, mapped pages in page heap. These | |
10359 | bytes can be used to fulfill allocation requests. They | |
10360 | always count towards virtual memory usage, and unless the | |
10361 | underlying memory is swapped out by the OS, they also count | |
10362 | towards physical memory usage. This property is not writable. | |
10363 | \termitem{'tcmalloc.pageheap_unmapped_bytes'}{-Int} | |
10364 | Number of bytes in free, unmapped pages in page heap. | |
10365 | These are bytes that have been released back to the OS, | |
10366 | possibly by one of the MallocExtension "Release" calls. | |
10367 | They can be used to fulfill allocation requests, but | |
10368 | typically incur a page fault. They always count towards | |
10369 | virtual memory usage, and depending on the OS, typically | |
10370 | do not count towards physical memory usage. | |
10371 | \end{description} | |
10372 | ||
10373 | \predicate[det]{set_malloc}{1}{+Property} | |
10374 | Set properties described in malloc_property/1. Currently | |
10375 | the only writable property is | |
10376 | \const{tcmalloc.max_total_thread_cache_bytes}. Setting an unknown | |
10377 | property raises a \const{domain_error} and setting a read-only property | |
10378 | raises a \const{permission_error} exception. | |
10379 | ||
10380 | \predicate[semidet]{thread_idle}{2}{:Goal, +Duration} | |
10381 | Indicates to the system that the calling thread will idle for some time | |
10382 | while calling \arg{Goal} as once/1. This call releases resources to the | |
10383 | OS to minimise the footprint of the calling thread while it waits. | |
10384 | Despite the name this predicate is always provided, also if the system | |
10385 | is not configured with tcmalloc or is single threaded. | |
10386 | \arg{Duration} is one of | |
10387 | ||
10388 | \begin{description} | |
10389 | \termitem{short}{} | |
10390 | Calls trim_stacks/0 and, if tcmalloc is used, calls | |
10391 | MallocExtension_MarkThreadTemporarilyIdle() which empties the thread's | |
10392 | malloc cache but preserves the cache itself. | |
10393 | ||
10394 | \termitem{long}{} | |
10395 | Calls garbage_collect/0 and trim_stacks/0 and, if tcmalloc is used, | |
10396 | calls MallocExtension_MarkThreadIdle() which releases all | |
10397 | thread-specific allocation datastructures. | |
10398 | \end{description} | |
10399 | \end{description} | |
10227 | 10400 | |
10228 | 10401 | |
10229 | 10402 | \section{Windows DDE interface} \label{sec:DDE} |
0 | #!/usr/bin/env perl | |
1 | ||
2 | sub printTeX | |
3 | { s/`([@\w]+)\s*<->([a-z]\w*)/\\index\{\l\1,\\both\{\2\}\}`\\classboth\{\1\}\{\2\}/g; | |
4 | s/`([@\w]+)\s*<-([a-z]\w*)/\\index\{\l\1,\\get\{\2\}\}`\\classget\{\1\}\{\2\}/g; | |
5 | s/`([@\w]+)\s*->([a-z]\w*)/\\index\{\l\1,\\send\{\2\}\}`\\classsend\{\1\}\{\2\}/g; | |
6 | s/<->([a-z]\w*)/\\both\{\1\}/g; | |
7 | s/<-([a-z]\w*)/\\get\{\1\}/g; | |
8 | s/->([a-z]\w*)/\\send\{\1\}/g; | |
9 | s/(^|\s|\()([a-z]\w+)\/((\d+|\[\d+(-|,)\d+\]))/\1\\index\{\2\/\3\}\\predref\{\2\}\{\3\}/g; | |
10 | s/(\s+|^)([a-z]\w+)\/\/((\d+|\[\d+(-|,)\d+\]))/\1\\index\{\2\/\/\3\}\\dcgref\{\2\}\{\3\}/g; | |
11 | s/(\w\.\w)\.(\s+[a-z])/\1.\\\2/g; | |
12 | s/(^|[^'"\$])<(\w[-~a-z]*\w)>/\1\\bnfmeta\{\2\}/g; | |
13 | s/\\class\{([<\\=>]*)\}/\\verb!\1!/g; | |
14 | s/==>/\$\\longrightarrow\$/g; | |
15 | s/^((\\index\{[^\}]+\})+) *$/\1%/; | |
16 | s/(\\index\{[^\}]*)\\index\{[^\}]*\}([^\}]*\})/\1\2/g; | |
17 | s/(\\class(get|send|both)\{)\\index\{[^\}]*\}/\1/g; | |
18 | s/(PL_[a-z_0-9]*)\(([^\)]*)\)/\\cfuncref\{\1\}\{\2\}/g; | |
19 | ||
20 | # Prolog special arguments ... | |
21 | # TBD: pick these up automatically from pl.sty | |
22 | ||
23 | s/\\file\{([^\}]*\\bnfmeta[^\}]*)\}/\\metafile\{\1\}/g; | |
24 | s/\\file\{([^\}]*\\arg[^\}]*)\}/\\metafile\{\1\}/g; | |
25 | s/\\file\{([^\}]+)\}/\\file@\1@/g; | |
26 | s/\\htmloutput\{([^\}]+)\}/\\htmloutput@\1@/g; | |
27 | ||
28 | s/\{#!\}/\{\\Sexe\}/g; | |
29 | s/\{#>\}/\{\\Scgt\}/g; | |
30 | s/\{#>=\}/\{\\Scge\}/g; | |
31 | s/\{#<\}/\{\\Sclt\}/g; | |
32 | s/\{#=<\}/\{\\Scle\}/g; | |
33 | s/\{#=\}/\{\\Sceq\}/g; | |
34 | s/\{#\\=\}/\{\\Scne\}/g; | |
35 | s/\{#\\\}/\{\\Snot\}/g; | |
36 | s/\{#\\\/\}/\{\\Sor\}/g; | |
37 | s/\{#\/\\\}/\{\\Sand\}/g; | |
38 | s/\{#<=>\}/\{\\Sequiv\}/g; | |
39 | s/\{#<=\}/\{\\Slimpl\}/g; | |
40 | s/\{#=>\}/\{\\Srimpl\}/g; | |
41 | s/\{#<==\}/\{\\Slimplies\}/g; | |
42 | s/\{#==>\}/\{\\Srimplies\}/g; | |
43 | s/\{#<==>\}/\{\\Scequal\}/g; | |
44 | s/\{#=\\=\}/\{\\Scine\}/g; | |
45 | s/\{#=:=\}/\{\\Scieq\}/g; | |
46 | s/\{#\}/\{\\Shash\}/g; | |
47 | s/\{!\}/\{\\Scut\}/g; | |
48 | s/\{,\}/\{\\Scomma\}/g; | |
49 | s/\{->\}/\{\\Sifthen\}/g; | |
50 | s/\{\*->\}/\{\\Ssoftcut\}/g; | |
51 | s/\{\.\}/\{\\Sdot\}/g; | |
52 | s/\{;\}/\{\\Ssemicolon\}/g; | |
53 | s/\{<\}/\{\\Slt\}/g; | |
54 | s/\{><\}/\{\\Sxor\}/g; | |
55 | s/\{=\}/\{\\Seq\}/g; | |
56 | s/\{=\.\.\}/\{\\Suniv\}/g; | |
57 | s/\{=:=\}/\{\\Saeq\}/g; | |
58 | s/\{=<\}/\{\\Sle\}/g; | |
59 | s/\{<=\}/\{\\Sel\}/g; | |
60 | s/\{==\}/\{\\Sequal\}/g; | |
61 | s/\{=@=\}/\{\\Sstructeq\}/g; | |
62 | s/\{\\=@=\}/\{\\Sstructneq\}/g; | |
63 | s/\{=\\=\}/\{\\Sane\}/g; | |
64 | s/\{>\}/\{\\Sgt\}/g; | |
65 | s/\{>=\}/\{\\Sge\}/g; | |
66 | s/\{>=<\}/\{\\Seqbowtie\}/g; | |
67 | s/\{>:<\}/\{\\Smappunify\}/g; | |
68 | s/\{:<\}/\{\\Smapselect\}/g; | |
69 | s/\{@<\}/\{\\Stlt\}/g; | |
70 | s/\{@=<\}/\{\\Stle\}/g; | |
71 | s/\{@>\}/\{\\Stgt\}/g; | |
72 | s/\{@>=\}/\{\\Stge\}/g; | |
73 | s/\{\\\+\}/\{\\Snot\}/g; | |
74 | s/\{\\=\}/\{\\Sne\}/g; | |
75 | s/\{\\==\}/\{\\Snequal\}/g; | |
76 | s/\{\^\}/\{\\Shat\}/g; | |
77 | s/\{\|\}/\{\\Sbar\}/g; | |
78 | s/\{\*\}/\{\\Stimes\}/g; | |
79 | s/\{\*\*\}/\{\\Spow\}/g; | |
80 | s/\{\+\}/\{\\Splus\}/g; | |
81 | s/\{-\}/\{\\Sminus\}/g; | |
82 | s/\{\/\}/\{\\Sdiv\}/g; | |
83 | s/\{\/\/\}/\{\\Sidiv\}/g; | |
84 | s/\{\/\\\}/\{\\Sand\}/g; | |
85 | s/\{<<\}/\{\\Slshift\}/g; | |
86 | s/\{>>\}/\{\\Srshift\}/g; | |
87 | s/\{\\\}/\{\\Sneg\}/g; | |
88 | s/\{\\\/\}/\{\\Sor\}/g; | |
89 | s/\{\$\}/\{\\Sdollar\}/g; | |
90 | s/\{\?\}/\{\\Squest\}/g; | |
91 | s/\{:\}/\{\\Smodule\}/g; | |
92 | s/\{:-\}/\{\\Sneck\}/g; | |
93 | s/\{\?-\}/\{\\Sdirective\}/g; | |
94 | s/\{-->\}/\{\\Sdcg\}/g; | |
95 | s/\{~\}/\{\\Stilde\}/g; | |
96 | s/\{%\}/\{\\Spercent\}/g; | |
97 | s/\{\{\}\}/\{\\Scurl\}/g; | |
98 | s/\{\[\|\]\}/\{\\Scons\}/g; | |
99 | s/\{xXX..\\\}/\{\\SxXX\}/g; | |
100 | ||
101 | s/\\file@([^@]+)@/\\file\{\1\}/g; | |
102 | s/\\htmloutput@([^@]+)@/\\htmloutput\{\1\}/g; | |
103 | ||
104 | print; | |
105 | } | |
106 | ||
107 | ||
108 | sub expandTabs | |
109 | { while ( ($i = index($_, "\t")) != $[-1 ) | |
110 | { $nspaces = 8 - $i % 8; | |
111 | for( $spaces="", $i=0; $i<$nspaces; $i++ ) | |
112 | { $spaces .= " "; | |
113 | } | |
114 | s/\t/$spaces/; | |
115 | } | |
116 | } | |
117 | ||
118 | ||
119 | sub | |
120 | expandSpecials | |
121 | { s/\^/\\verb!^!/g; | |
122 | s/\|/\\verb!|!/g; | |
123 | } | |
124 | ||
125 | ||
126 | sub printCode | |
127 | { print; | |
128 | while (<ARGV> ) | |
129 | { &expandTabs; | |
130 | print; | |
131 | if ( /\\end\{(code|verbatim)\}/ ) | |
132 | { return; | |
133 | } | |
134 | } | |
135 | } | |
136 | ||
137 | ||
138 | sub printPceCode | |
139 | { $line = 0; | |
140 | print; | |
141 | while (<ARGV> ) | |
142 | { $line++; | |
143 | &expandTabs; | |
144 | if ( /\\end\{pcecode\}/ ) | |
145 | { print; | |
146 | return; | |
147 | } | |
148 | chomp; | |
149 | print "\\lineno{$line}\\verb`$_`\n"; | |
150 | } | |
151 | } | |
152 | ||
153 | ||
154 | sub skiptonext | |
155 | { while (<ARGV>) | |
156 | { if ( ! /^\s*$/ ) | |
157 | { return; | |
158 | } | |
159 | last; | |
160 | } | |
161 | while (<ARGV>) | |
162 | { if ( ! /^\s*$/ ) | |
163 | { return; | |
164 | } | |
165 | } | |
166 | } | |
167 | ||
168 | # MAIN PROGRAM | |
169 | ||
170 | while (<>) | |
171 | { while ( /\\begin\{pcecode\}/ ) | |
172 | { &printPceCode; | |
173 | print "\n\\noindent\n"; | |
174 | &skiptonext; | |
175 | } | |
176 | while ( /\\begin\{(code|verbatim)\}/ ) | |
177 | { &printCode; | |
178 | print "\n\\noindent\n"; | |
179 | &skiptonext; | |
180 | } | |
181 | &printTeX; | |
182 | } |
3397 | 3397 | \cfunction{int}{PL_initialise}{int argc, char **argv} |
3398 | 3398 | Initialises the SWI-Prolog heap and stacks, restores the Prolog |
3399 | 3399 | state, loads the system and personal initialisation files, |
3400 | runs the initialization/1 hooks and finally runs the | |
3401 | \argoption{-g}{goal} hook. | |
3400 | runs the initialization/1 hooks and finally runs the initialization | |
3401 | goals registered using \argoption{-g}{goal}. | |
3402 | 3402 | |
3403 | 3403 | Special consideration is required for \verb$argv[0]$. On {\bf Unix}, |
3404 | 3404 | this argument passes the part of the command line that is used |
3405 | 3405 | to locate the executable. Prolog uses this to find the file holding |
3406 | 3406 | the running executable. The {\bf Windows} version uses this to find |
3407 | 3407 | a \jargon{module} of the running executable. If the specified module |
3408 | cannot be found, it tries the module \const{libpl.dll}, containing | |
3408 | cannot be found, it tries the module \const{libswipl.dll}, containing | |
3409 | 3409 | the Prolog runtime kernel. In all these cases, the resulting file is |
3410 | 3410 | used for two purposes: |
3411 | 3411 | |
3451 | 3451 | |
3452 | 3452 | A good setup in Windows is to add SWI-Prolog's \file{bin} directory |
3453 | 3453 | to your \env{PATH} and either pass a module holding a saved state, or |
3454 | \verb$"libpl.dll"$ as \verb$argv[0]$. If the Prolog state is attached | |
3455 | to a DLL (see the \cmdlineoption{-dll} option of \program{swipl-ld}), pass | |
3456 | the name of this DLL. | |
3454 | \verb$"libswipl.dll"$ as \verb$argv[0]$. If the Prolog state is attached | |
3455 | to a DLL (see the \cmdlineoption{-dll} option of \program{swipl-ld}), | |
3456 | pass the name of this DLL. | |
3457 | 3457 | |
3458 | 3458 | \cfunction{int}{PL_is_initialised}{int *argc, char ***argv} |
3459 | 3459 | Test whether the Prolog engine is already initialised. Returns |
58 | 58 | |
59 | 59 | \newcommand{\vmajor}{8} |
60 | 60 | \newcommand{\vminor}{1} |
61 | \newcommand{\vpatch}{26} | |
61 | \newcommand{\vpatch}{28} | |
62 | 62 | \newcommand{\vtag}{} |
63 | \newcommand{\vmonth}{March} | |
63 | \newcommand{\vmonth}{April} | |
64 | 64 | \newcommand{\vyear}{2020} |
65 | 65 | |
66 | 66 | #ifdef BOOK |
829 | 829 | True if \arg{Module} exports the given operators. Each exported |
830 | 830 | operator is represented as a term \term{op}{Pri,Assoc,Name}. |
831 | 831 | Succeeds with an empty list if the module exports no operators. |
832 | \termitem{size}{-Bytes} | |
833 | Total size in bytes used to represent the module. This includes | |
834 | the module itself, its (hash) tables and the summed size of | |
835 | all predicates defined in this module. See also | |
836 | the \term{size}{Bytes} property in predicate_property/2. | |
832 | 837 | \termitem{program_size}{-Bytes} |
833 | 838 | Memory (in bytes) used for storing the predicates of this |
834 | 839 | module. This figure includes the predicate header and clauses. |
835 | Future versions might give a more precise number, including | |
836 | e.g., the clause index tables. | |
837 | 840 | \termitem{program_space}{-Bytes} |
838 | 841 | If present, this number limits the \const{program_size}. See |
839 | 842 | set_module/1. |
1604 | 1604 | \prologflag{readline}) and 15 otherwise. |
1605 | 1605 | |
1606 | 1606 | \prologflagitem{home}{atom}{r} |
1607 | SWI-Prolog's notion of the home directory. SWI-Prolog uses its home | |
1608 | directory to find its startup file as | |
1609 | \file{<home>/boot32.prc} (32-bit machines) or | |
1610 | \file{<home>/boot64.prc} (64-bit machines) and to find its library as | |
1611 | \file{<home>/library}. | |
1607 | SWI-Prolog's notion of the home directory. SWI-Prolog uses its home | |
1608 | directory to find its startup file as \file{<home>/boot.prc} and to find | |
1609 | its library as \file{<home>/library}. Some installations may put | |
1610 | architecture independent files in a \jargon{shared home} and also | |
1611 | define \prologflag{shared_home}. System files can be found using | |
1612 | absolute_file_name/3 as \term{swi}{file}. See file_search_path/2. | |
1612 | 1613 | |
1613 | 1614 | \prologflagitem{hwnd}{integer}{r} |
1614 | 1615 | In \program{swipl-win.exe}, this refers to the MS-Windows window handle of |
1946 | 1947 | \prologflagitem{saved_program}{bool}{r} |
1947 | 1948 | If present and \const{true}, Prolog has been started from a state saved |
1948 | 1949 | with qsave_program/[1,2]. |
1950 | ||
1951 | \prologflagitem{shared_home}{atom}{r} | |
1952 | Indicates that part of the SWI-Prolog system files are installed in | |
1953 | \file{<prefix>/share/swipl} instead of in the home at the | |
1954 | \file{<prefix>/lib/swipl}. This flag indicates the location of this | |
1955 | \emph{shared home} and the directory is added to the file seach path | |
1956 | \const{swi}. See file_search_path/2 and the flag \prologflag{home}. | |
1949 | 1957 | |
1950 | 1958 | \prologflagitem{shared_object_extension}{atom}{r} |
1951 | 1959 | Extension used by the operating system for shared objects. \fileext{so} |
2553 | 2561 | \end{description} |
2554 | 2562 | |
2555 | 2563 | |
2556 | ||
2557 | \section{Garbage Collection} \label{sec:gc} | |
2558 | ||
2559 | SWI-Prolog provides garbage collection, last-call optimization and atom | |
2560 | garbage collection. These features are controlled using Prolog flags | |
2561 | (see current_prolog_flag/2). | |
2562 | ||
2563 | ||
2564 | \section{The SWI-Prolog syntax} \label{sec:syntax} | |
2564 | \section{The SWI-Prolog syntax} \label{sec:syntax} | |
2565 | 2565 | |
2566 | 2566 | SWI-Prolog syntax is close to ISO-Prolog standard syntax, which is based |
2567 | 2567 | on the Edinburgh Prolog syntax. A formal description can be found in the |
48 | 48 | :- initialization(clean_pldoc, prepare_state). |
49 | 49 | |
50 | 50 | pltotex(File, Options) :- |
51 | set_prolog_flag(pldoc_to_tex, true), | |
51 | 52 | markdown_file(File), |
52 | 53 | !, |
53 | 54 | preload(Options), |
57 | 58 | summaries(Out, LatexOptions, LatexOptions0), |
58 | 59 | doc_latex(MarkDown, Out, LatexOptions). |
59 | 60 | pltotex(Lib, Options) :- |
61 | set_prolog_flag(pldoc_to_tex, true), | |
60 | 62 | ( file_name_extension(_, pl, Lib) |
61 | 63 | -> Spec = Lib |
62 | 64 | ; atom_to_term(Lib, Spec, _) |
0 | #!/bin/bash -f | |
1 | ||
2 | from="$1" | |
3 | to="$2" | |
4 | ||
5 | if [ -z "$from" ]; then | |
6 | echo "Usage: $0 from to" | |
7 | fi | |
8 | ||
9 | files=`find . -name '*.[ch]' | xargs grep -l "$1"` | |
10 | for f in $files; do | |
11 | cp -p $f $f.bak | |
12 | sed "s|$1|$2|g" $f.bak > $f | |
13 | if cmp -s $f.bak $f; then | |
14 | mv $f.bak $f # no change | |
15 | else | |
16 | echo " modified $f" | |
17 | fi | |
18 | done |
410 | 410 | atoms} \predicatesummary{make}{0}{Reconsult all changed source files} |
411 | 411 | \predicatesummary{make_directory}{1}{Create a folder on the file system} |
412 | 412 | \predicatesummary{make_library_index}{1}{Create autoload file INDEX.pl} |
413 | \predicatesummary{make_library_index}{2}{Create selective autoload file | |
414 | INDEX.pl} \predicatesummary{map_assoc}{2}{Map association tree} | |
413 | \predicatesummary{malloc_property}{1}{Property of the allocator} | |
414 | \predicatesummary{make_library_index}{2}{Create selective autoload file INDEX.pl} \predicatesummary{map_assoc}{2}{Map association tree} | |
415 | 415 | \predicatesummary{map_assoc}{3}{Map association tree} |
416 | 416 | \predicatesummary{dict_create}{3}{Create a dict from data} |
417 | 417 | \predicatesummary{dict_pairs}{3}{Convert between dict and list of pairs} |
629 | 629 | open file} \predicatesummary{set_flag}{2}{Set value of a flag} |
630 | 630 | \predicatesummary{set_input}{1}{Set current input stream from a stream} |
631 | 631 | \predicatesummary{set_locale}{1}{Set the default local} |
632 | \predicatesummary{set_malloc}{1}{Set memory allocator property} | |
632 | 633 | \predicatesummary{set_module}{1}{Set properties of a module} |
633 | 634 | \predicatesummary{set_output}{1}{Set current output stream from a |
634 | 635 | stream} \predicatesummary{set_prolog_IO}{3}{Prepare streams for |
713 | 714 | \predicatesummary{thread_get_message}{1}{Wait for message} |
714 | 715 | \predicatesummary{thread_get_message}{2}{Wait for message in a queue} |
715 | 716 | \predicatesummary{thread_get_message}{3}{Wait for message in a queue} |
717 | \predicatesummary{thread_idle}{2}{Reduce footprint while waiting} | |
716 | 718 | \predicatesummary{thread_initialization}{1}{Run action at start of thread} |
717 | 719 | \predicatesummary{thread_join}{1}{Wait for Prolog task-completion} |
718 | 720 | \predicatesummary{thread_join}{2}{Wait for Prolog task-completion} |
359 | 359 | If the thread is an engine that is currently attached to a thread, |
360 | 360 | \arg{ThreadId} is the thread that executes the engine. |
361 | 361 | |
362 | \termitem{size}{Bytes} | |
363 | The amount of memory associated with this thread. This includes the | |
364 | thread structure, its stacks, its default message queue, its clauses | |
365 | in its thread local dynamic predicates (see thread_local/1) and memory | |
366 | used for representing thread-local answer tries (see \secref{tabling}). | |
367 | ||
362 | 368 | \termitem{system_thread_id}{Integer} |
363 | 369 | Thread identifier used by the operating system for the calling thread. |
364 | 370 | Not available on all OSes. This is the same as the Prolog flag |
64 | 64 | install_dll(${LibArchive_LIBRARIES}) |
65 | 65 | |
66 | 66 | pkg_doc(archive |
67 | SOURCE archive.pl archive4pl.tex) | |
67 | SOURCE archive.pl archive4pl.tex | |
68 | DEPENDS archive) | |
68 | 69 | |
69 | 70 | endif(LibArchive_FOUND) |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2015, University of Amsterdam | |
6 | VU University Amsterdam | |
5 | Copyright (c) 2015-2020, University of Amsterdam | |
6 | VU University Amsterdam | |
7 | CWI, Amsterdam | |
7 | 8 | All rights reserved. |
8 | 9 | |
9 | 10 | Redistribution and use in source and binary forms, with or without |
158 | 159 | } |
159 | 160 | |
160 | 161 | static int bdb_close_env(dbenvh *env, int silent); |
161 | ||
162 | static int bdb_close(dbh *db); | |
162 | 163 | |
163 | 164 | /******************************* |
164 | 165 | * DB_ENV SYMBOL WRAPPER * |
743 | 744 | dbh->env = env; |
744 | 745 | NOSIG(rval=db_create(&dbh->db, env->env, 0)); |
745 | 746 | if ( rval ) |
747 | { dbh->db = NULL; | |
748 | dbh->symbol = 0; | |
746 | 749 | return db_status(rval, file); |
750 | } | |
747 | 751 | |
748 | 752 | DEBUG(Sdprintf("New DB at %p\n", dbh->db)); |
749 | 753 | |
750 | 754 | if ( !db_options(options, dbh, &subdb) ) |
751 | { dbh->db->close(dbh->db, 0); | |
755 | { bdb_close(dbh); | |
752 | 756 | return FALSE; |
753 | 757 | } |
754 | 758 | |
761 | 765 | #endif |
762 | 766 | |
763 | 767 | if ( rval ) |
764 | { dbh->db->close(dbh->db, 0); | |
768 | { bdb_close(dbh); | |
765 | 769 | return db_status_db(rval, dbh); |
766 | 770 | } |
767 | 771 | |
768 | 772 | return unify_db(handle, dbh); |
773 | } | |
774 | ||
775 | ||
776 | static int | |
777 | bdb_close(dbh *db) | |
778 | { int rval; | |
779 | ||
780 | DEBUG(Sdprintf("Close DB at %p\n", db->db)); | |
781 | NOSIG(rval = db->db->close(db->db, 0); | |
782 | db->db = NULL; | |
783 | db->symbol = 0); | |
784 | ||
785 | return rval; | |
769 | 786 | } |
770 | 787 | |
771 | 788 | |
774 | 791 | { dbh *db; |
775 | 792 | |
776 | 793 | if ( get_db(handle, &db) ) |
777 | { int rval; | |
778 | ||
779 | DEBUG(Sdprintf("Close DB at %p\n", db->db)); | |
780 | NOSIG(rval = db->db->close(db->db, 0); | |
781 | db->db = NULL; | |
782 | db->symbol = 0); | |
783 | ||
784 | return db_status(rval, handle); | |
794 | { if ( !db->db || !db->symbol ) | |
795 | return PL_existence_error("db", handle); | |
796 | return db_status(bdb_close(db), handle); | |
785 | 797 | } |
786 | 798 | |
787 | 799 | return FALSE; |
795 | 807 | if ( PL_get_blob(t, &data, NULL, &type) && type == &db_blob) |
796 | 808 | { dbh *p = data; |
797 | 809 | |
798 | if ( p->symbol ) | |
810 | if ( p->db && p->symbol ) | |
799 | 811 | return TRUE; |
800 | 812 | |
801 | 813 | return FALSE; |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2015, VU University Amsterdam | |
5 | Copyright (c) 2015-2020, VU University Amsterdam | |
6 | CWI, Amsterdam | |
6 | 7 | All rights reserved. |
7 | 8 | |
8 | 9 | Redistribution and use in source and binary forms, with or without |
70 | 71 | |
71 | 72 | :- begin_tests(bdb). |
72 | 73 | |
73 | test(loop, PairsOut =@= PairsIn) :- | |
74 | DBFile = 'test.db', | |
74 | :- multifile user:file_search_path/1. | |
75 | user:file_search_path(test_tmp_dir, '.'). | |
76 | ||
77 | tmp_output(Base, File) :- | |
78 | absolute_file_name(test_tmp_dir(Base), | |
79 | File, | |
80 | [ access(write) | |
81 | ]). | |
82 | ||
83 | test(loop, | |
84 | [ setup(tmp_output('test.db', DBFile)), | |
85 | cleanup(delete_existing_file(DBFile)), | |
86 | PairsOut =@= PairsIn | |
87 | ]) :- | |
75 | 88 | delete_existing_file(DBFile), |
76 | 89 | setof(Type-Data, data(Type, Data), PairsIn), |
77 | 90 | bdb_open(DBFile, update, DB, []), |
78 | 91 | forall(member(Type-Data, PairsIn), |
79 | 92 | bdb_put(DB, Type, Data)), |
80 | 93 | setof(Type-Data, bdb_enum(DB, Type, Data), PairsOut), |
81 | bdb_close(DB), | |
82 | delete_existing_file(DBFile). | |
83 | test(no_duplicates, Mies == mies) :- | |
84 | DBFile = 'test.db', | |
94 | bdb_close(DB). | |
95 | test(no_duplicates, | |
96 | [ setup(tmp_output('test.db', DBFile)), | |
97 | cleanup(delete_existing_file(DBFile)), | |
98 | Mies == mies | |
99 | ]) :- | |
85 | 100 | delete_existing_file(DBFile), |
86 | 101 | bdb_open(DBFile, update, DB, [duplicates(false)]), |
87 | 102 | bdb_put(DB, aap, noot), |
88 | 103 | bdb_put(DB, aap, mies), |
89 | 104 | bdb_get(DB, aap, Mies), |
90 | bdb_close(DB), | |
91 | delete_existing_file(DBFile). | |
92 | test(duplicates, Out == [1,2,3,4,5,6,7,8,9,10]) :- | |
93 | DBFile = 'test.db', | |
105 | bdb_close(DB). | |
106 | test(duplicates, | |
107 | [ setup(tmp_output('test.db', DBFile)), | |
108 | cleanup(delete_existing_file(DBFile)), | |
109 | Out == [1,2,3,4,5,6,7,8,9,10] | |
110 | ]) :- | |
94 | 111 | delete_existing_file(DBFile), |
95 | 112 | bdb_open(DBFile, update, DB, [duplicates(true)]), |
96 | 113 | forall(between(1, 10, X), |
97 | 114 | forall(between(1, 10, Y), |
98 | 115 | bdb_put(DB, X, Y))), |
99 | 116 | bdb_getall(DB, 5, Out), |
100 | bdb_close(DB), | |
101 | delete_existing_file(DBFile). | |
117 | bdb_close(DB). | |
102 | 118 | |
103 | 119 | :- end_tests(bdb). |
96 | 96 | ################ |
97 | 97 | # Tests |
98 | 98 | |
99 | test_libs(cgi crypt memfile process readutil socket stream time uri) | |
99 | test_libs(cgi crypt memfile process readutil socket af_unix stream time uri) | |
100 | 100 | |
101 | 101 | ################ |
102 | 102 | # Documentation |
66 | 66 | \InputIfFileExists{uid.tex}{}{} |
67 | 67 | \InputIfFileExists{syslog.tex}{}{} |
68 | 68 | \input{socket.tex} |
69 | ||
70 | \subsection{Unix domain sockets} | |
71 | \label{sec:af-unix-sockets} | |
72 | ||
73 | Unix domain sockets (sockets with address family AF_UNIX) are | |
74 | represented as a (socket) file in the file system. They can only be used | |
75 | to connect processes on the same host. The main advantage of AF_UNIX | |
76 | sockets is that name conflicts are much easier to manage than port | |
77 | conflicts and that access is determined by the file system permission | |
78 | rules. | |
79 | ||
80 | \begin{description} | |
81 | \predicate{unix_domain_socket}{1}{-Socket} | |
82 | Creates an AF_UNIX-domain stream-socket and unifies an identifier to | |
83 | it with \arg{Socket}. This predicate does not exist if the OS does | |
84 | not support the AF_UNIX address family (e.g. MS-Windows). | |
85 | ||
86 | Unix domain socket affect tcp_connect/2 (for clients) and tcp_bind/2 and | |
87 | tcp_accept/3 (for servers). The address is an atom or string that is | |
88 | handled as a file name. On most systems the length of this file name is | |
89 | limited to 128 bytes (including null terminator), but according to the | |
90 | Linux documentation (unix(7)), portable applications must keep the | |
91 | address below 92 bytes. Note that these lengths are in \emph{bytes}. | |
92 | Non-ascii characters may be represented as multiple bytes. If the length | |
93 | limit is exceeded a \term{representation_error}{af_unix_name} exception | |
94 | is raised. | |
95 | \end{description} | |
69 | 96 | |
70 | 97 | \subsection{UDP protocol support} |
71 | 98 | \label{sec:udp-sockets} |
51 | 51 | #cmakedefine HAVE_SYS_TIME_H @HAVE_SYS_TIME_H@ |
52 | 52 | #cmakedefine HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@ |
53 | 53 | #cmakedefine HAVE_SYS_WAIT_H @HAVE_SYS_WAIT_H@ |
54 | #cmakedefine HAVE_SYS_UN_H @HAVE_SYS_UN_H@ | |
54 | 55 | #cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@ |
55 | 56 | #cmakedefine HAVE_UTIME @HAVE_UTIME@ |
56 | 57 | #cmakedefine HAVE_UTIME_H @HAVE_UTIME_H@ |
1 | 1 | Author: Jan Wielemaker |
2 | 2 | E-mail: J.Wielemaker@vu.nl |
3 | 3 | WWW: http://www.swi-prolog.org |
4 | Copyright (c) 2004-2018, University of Amsterdam | |
4 | Copyright (c) 2004-2020, University of Amsterdam | |
5 | 5 | VU University Amsterdam |
6 | 6 | CWI, Amsterdam |
7 | 7 | All rights reserved. |
178 | 178 | { int magic; /* PLSOCK_MAGIC */ |
179 | 179 | SOCKET socket; /* The OS socket */ |
180 | 180 | int flags; /* Misc flags */ |
181 | int domain; /* AF_* */ | |
181 | 182 | atom_t symbol; /* <socket>(%p) */ |
182 | 183 | IOSTREAM * input; /* input stream */ |
183 | 184 | IOSTREAM * output; /* output stream */ |
516 | 517 | int |
517 | 518 | is_nbio_socket(nbio_sock_t socket) |
518 | 519 | { return socket && socket->magic == PLSOCK_MAGIC; |
520 | } | |
521 | ||
522 | int | |
523 | nbio_domain(nbio_sock_t socket) | |
524 | { return socket->domain; | |
519 | 525 | } |
520 | 526 | |
521 | 527 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
856 | 862 | { closesocket(sock); |
857 | 863 | return NULL; |
858 | 864 | } |
865 | s->domain = domain; | |
859 | 866 | #ifdef __WINDOWS__ |
860 | 867 | /* On older versions of Windows (win7 and before) the default send |
861 | 868 | buffer size is only 8k. On a high latency link this can seriously |
168 | 168 | |
169 | 169 | extern int nbio_wait(nbio_sock_t socket, nbio_request); |
170 | 170 | extern SOCKET nbio_fd(nbio_sock_t socket); |
171 | extern int nbio_domain(nbio_sock_t socket); | |
171 | 172 | |
172 | 173 | extern int nbio_unify_ip4(term_t ip4, unsigned long hip); |
173 | 174 | extern int nbio_get_ip(term_t ip4, struct in_addr *ip); |
1775 | 1775 | if ( info->envp ) |
1776 | 1776 | { execve(info->exe, info->argv, info->envp); |
1777 | 1777 | } else |
1778 | { extern char **environ; | |
1779 | ||
1778 | { | |
1779 | #ifdef HAVE__NSGETENVIRON | |
1780 | char **environ = *_NSGetEnviron(); | |
1781 | #else | |
1782 | extern char **environ; | |
1783 | #endif | |
1780 | 1784 | execve(info->exe, info->argv, environ); |
1781 | 1785 | } |
1782 | 1786 |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2000-2018, University of Amsterdam | |
5 | Copyright (c) 2000-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | CWI, Amsterdam |
8 | 8 | All rights reserved. |
72 | 72 | #else |
73 | 73 | #define GET_ERRNO errno |
74 | 74 | #define GET_H_ERRNO h_errno |
75 | #endif | |
76 | ||
77 | #ifdef HAVE_SYS_UN_H | |
78 | #include <sys/un.h> | |
79 | #else | |
80 | /* Windows does not have the header, but does have AF_UNIX? */ | |
81 | #undef AF_UNIX | |
75 | 82 | #endif |
76 | 83 | |
77 | 84 | #if !defined(HAVE_IP_MREQN) && defined(__APPLE__) |
95 | 102 | static atom_t ATOM_ip_add_membership; /* "ip_add_membership" */ |
96 | 103 | static atom_t ATOM_ip_drop_membership; /* "ip_drop_membership" */ |
97 | 104 | static atom_t ATOM_sndbuf; /* "sndbuf" */ |
105 | static atom_t ATOM_af_unix; /* "af_unix" */ | |
98 | 106 | static functor_t FUNCTOR_socket1; /* $socket(Id) */ |
99 | 107 | |
100 | 108 | static int get_socket_from_stream(term_t t, IOSTREAM **s, nbio_sock_t *sp); |
544 | 552 | |
545 | 553 | |
546 | 554 | static foreign_t |
547 | create_socket(term_t socket, int type) | |
555 | create_socket(int domain, term_t socket, int type) | |
548 | 556 | { nbio_sock_t sock; |
549 | 557 | |
550 | if ( !(sock = nbio_socket(AF_INET, type, 0)) ) | |
558 | if ( !(sock = nbio_socket(domain, type, 0)) ) | |
551 | 559 | return FALSE; |
552 | 560 | |
553 | 561 | return tcp_unify_socket(socket, sock); |
556 | 564 | |
557 | 565 | static foreign_t |
558 | 566 | tcp_socket(term_t socket) |
559 | { return create_socket(socket, SOCK_STREAM); | |
567 | { return create_socket(AF_INET, socket, SOCK_STREAM); | |
560 | 568 | } |
561 | 569 | |
562 | 570 | |
563 | 571 | static foreign_t |
564 | 572 | udp_socket(term_t socket) |
565 | { return create_socket(socket, SOCK_DGRAM); | |
566 | } | |
567 | ||
573 | { return create_socket(AF_INET, socket, SOCK_DGRAM); | |
574 | } | |
575 | ||
576 | ||
577 | #ifdef AF_UNIX | |
578 | static foreign_t | |
579 | unix_domain_socket(term_t socket) | |
580 | { return create_socket(AF_UNIX, socket, SOCK_STREAM); | |
581 | } | |
582 | ||
583 | static int | |
584 | af_unix_address(term_t Address, | |
585 | struct sockaddr_un *sockaddr, int *addrlen, | |
586 | int flags) | |
587 | { char *file_name_chars; | |
588 | int nmlen; | |
589 | ||
590 | if ( !PL_get_file_name(Address, &file_name_chars, | |
591 | PL_FILE_OSPATH|flags) ) | |
592 | return FALSE; | |
593 | nmlen = strlen(file_name_chars); | |
594 | if ( nmlen >= sizeof(sockaddr->sun_path) ) | |
595 | { PL_representation_error("af_unix_name"); | |
596 | return FALSE; | |
597 | } | |
598 | ||
599 | memset(sockaddr, 0, sizeof(*sockaddr)); | |
600 | sockaddr->sun_family = AF_UNIX; | |
601 | memcpy(sockaddr->sun_path, file_name_chars, nmlen); | |
602 | *addrlen = offsetof(struct sockaddr_un, sun_path) + nmlen + 1; | |
603 | ||
604 | return TRUE; | |
605 | } | |
606 | ||
607 | #endif /*AF_UNIX*/ | |
608 | ||
609 | static int | |
610 | af_unix_connect(nbio_sock_t sock, term_t Address) | |
611 | { | |
612 | #ifdef AF_UNIX | |
613 | if ( nbio_domain(sock) == AF_UNIX ) | |
614 | { struct sockaddr_un sockaddr; | |
615 | int addrlen; | |
616 | ||
617 | return ( af_unix_address(Address, &sockaddr, &addrlen, PL_FILE_READ) && | |
618 | nbio_connect(sock, (struct sockaddr *)&sockaddr, addrlen) == 0 ); | |
619 | } else | |
620 | #endif | |
621 | { return -1; | |
622 | } | |
623 | } | |
624 | ||
625 | static int | |
626 | af_unix_bind(nbio_sock_t sock, term_t Address) | |
627 | { | |
628 | #ifdef AF_UNIX | |
629 | if ( nbio_domain(sock) == AF_UNIX ) | |
630 | { struct sockaddr_un sockaddr; | |
631 | int addrlen; | |
632 | ||
633 | return ( af_unix_address(Address, &sockaddr, &addrlen, 0) && | |
634 | nbio_bind(sock, (struct sockaddr *)&sockaddr, addrlen) == 0 ); | |
635 | } else | |
636 | #endif | |
637 | { return -1; | |
638 | } | |
639 | } | |
568 | 640 | |
569 | 641 | static foreign_t |
570 | 642 | pl_connect(term_t Socket, term_t Address) |
571 | 643 | { nbio_sock_t sock; |
572 | 644 | struct sockaddr_in sockaddr; |
573 | ||
574 | if ( !tcp_get_socket(Socket, &sock) || | |
575 | !nbio_get_sockaddr(Address, &sockaddr, NULL) ) | |
645 | int rc; | |
646 | ||
647 | if ( !tcp_get_socket(Socket, &sock) ) | |
648 | return FALSE; | |
649 | ||
650 | if ( (rc=af_unix_connect(sock, Address)) != -1 ) | |
651 | return rc; | |
652 | ||
653 | if ( !nbio_get_sockaddr(Address, &sockaddr, NULL) ) | |
576 | 654 | return FALSE; |
577 | 655 | |
578 | 656 | if ( nbio_connect(sock, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == 0 ) |
584 | 662 | |
585 | 663 | static foreign_t |
586 | 664 | pl_bind(term_t Socket, term_t Address) |
587 | { struct sockaddr_in sockaddr; | |
588 | nbio_sock_t socket; | |
589 | term_t varport = 0; | |
590 | ||
591 | memset(&sockaddr, 0, sizeof(sockaddr)); | |
592 | ||
593 | if ( !tcp_get_socket(Socket, &socket) || | |
594 | !nbio_get_sockaddr(Address, &sockaddr, &varport) ) | |
595 | return FALSE; | |
596 | ||
597 | if ( nbio_bind(socket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0 ) | |
598 | return FALSE; | |
599 | ||
600 | if ( varport ) | |
601 | { SOCKET fd = nbio_fd(socket); | |
602 | struct sockaddr_in addr; | |
665 | { nbio_sock_t socket; | |
666 | int rc; | |
667 | ||
668 | if ( !tcp_get_socket(Socket, &socket) ) | |
669 | return FALSE; | |
670 | ||
671 | if ( (rc=af_unix_bind(socket, Address)) != -1 ) | |
672 | { return rc; | |
673 | } else | |
674 | { struct sockaddr_in sockaddr; | |
675 | term_t varport = 0; | |
676 | ||
677 | memset(&sockaddr, 0, sizeof(sockaddr)); | |
678 | if ( !nbio_get_sockaddr(Address, &sockaddr, &varport) ) | |
679 | return FALSE; | |
680 | ||
681 | if ( nbio_bind(socket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0 ) | |
682 | return FALSE; | |
683 | ||
684 | if ( varport ) | |
685 | { SOCKET fd = nbio_fd(socket); | |
686 | struct sockaddr_in addr; | |
603 | 687 | #ifdef __WINDOWS__ |
604 | int len = sizeof(addr); | |
688 | int len = sizeof(addr); | |
605 | 689 | #else |
606 | socklen_t len = sizeof(addr); | |
607 | #endif | |
608 | ||
609 | if ( getsockname(fd, (struct sockaddr *) &addr, &len) ) | |
610 | return nbio_error(GET_ERRNO, TCP_ERRNO); | |
611 | return PL_unify_integer(varport, ntohs(addr.sin_port)); | |
612 | } | |
613 | ||
614 | return TRUE; | |
690 | socklen_t len = sizeof(addr); | |
691 | #endif | |
692 | ||
693 | if ( getsockname(fd, (struct sockaddr *) &addr, &len) ) | |
694 | return nbio_error(GET_ERRNO, TCP_ERRNO); | |
695 | return PL_unify_integer(varport, ntohs(addr.sin_port)); | |
696 | } | |
697 | ||
698 | return TRUE; | |
699 | } | |
615 | 700 | } |
616 | 701 | |
617 | 702 | |
618 | 703 | static foreign_t |
619 | 704 | pl_accept(term_t Master, term_t Slave, term_t Peer) |
620 | 705 | { nbio_sock_t master, slave; |
621 | struct sockaddr_in addr; | |
622 | socklen_t addrlen = sizeof(addr); | |
623 | 706 | |
624 | 707 | if ( !tcp_get_socket(Master, &master) ) |
625 | 708 | return FALSE; |
626 | 709 | |
627 | if ( !(slave = nbio_accept(master, (struct sockaddr*)&addr, &addrlen)) ) | |
628 | return FALSE; | |
629 | /* TBD: close on failure */ | |
630 | if ( nbio_unify_ip4(Peer, ntohl(addr.sin_addr.s_addr)) && | |
631 | tcp_unify_socket(Slave, slave) ) | |
710 | #ifdef AF_UNIX | |
711 | if ( nbio_domain(master) == AF_UNIX ) | |
712 | { struct sockaddr_un addr; | |
713 | socklen_t addrlen = sizeof(addr); | |
714 | ||
715 | if ( !PL_unify_atom(Peer, ATOM_af_unix) ) | |
716 | return FALSE; | |
717 | if ( !(slave = nbio_accept(master, (struct sockaddr*)&addr, &addrlen)) ) | |
718 | return FALSE; | |
719 | } else | |
720 | #endif | |
721 | { struct sockaddr_in addr; | |
722 | socklen_t addrlen = sizeof(addr); | |
723 | ||
724 | if ( !(slave = nbio_accept(master, (struct sockaddr*)&addr, &addrlen)) ) | |
725 | return FALSE; | |
726 | if ( !nbio_unify_ip4(Peer, ntohl(addr.sin_addr.s_addr)) ) | |
727 | goto failure; | |
728 | } | |
729 | ||
730 | if ( tcp_unify_socket(Slave, slave) ) | |
632 | 731 | return TRUE; |
633 | 732 | |
733 | failure: | |
734 | nbio_closesocket(slave); | |
634 | 735 | return FALSE; |
635 | 736 | } |
636 | 737 | |
699 | 800 | ATOM_ip_add_membership = PL_new_atom("ip_add_membership"); |
700 | 801 | ATOM_ip_drop_membership = PL_new_atom("ip_drop_membership"); |
701 | 802 | ATOM_sndbuf = PL_new_atom("sndbuf"); |
803 | ATOM_af_unix = PL_new_atom("af_unix"); | |
702 | 804 | |
703 | 805 | FUNCTOR_socket1 = PL_new_functor(PL_new_atom("$socket"), 1); |
704 | 806 | |
718 | 820 | PL_register_foreign("udp_receive", 4, udp_receive, 0); |
719 | 821 | PL_register_foreign("udp_send", 4, udp_send, 0); |
720 | 822 | |
823 | #ifndef __WINDOWS__ | |
824 | PL_register_foreign("unix_domain_socket", 1, unix_domain_socket, 0); | |
825 | #endif | |
826 | ||
721 | 827 | #ifdef O_DEBUG |
722 | 828 | PL_register_foreign("tcp_debug", 1, pl_debug, 0); |
723 | 829 | #endif |
181 | 181 | :- use_foreign_library(foreign(socket), install_socket). |
182 | 182 | :- public tcp_debug/1. % set debugging. |
183 | 183 | |
184 | :- if(current_predicate(unix_domain_socket/1)). | |
185 | :- export(unix_domain_socket/1). % -Socket | |
186 | :- endif. | |
187 | ||
184 | 188 | %! tcp_socket(-SocketId) is det. |
185 | 189 | % |
186 | 190 | % Creates an INET-domain stream-socket and unifies an identifier |
260 | 264 | |
261 | 265 | %! tcp_accept(+Socket, -Slave, -Peer) is det. |
262 | 266 | % |
263 | % This predicate waits on a server socket for a connection request | |
264 | % by a client. On success, it creates a new socket for the client | |
265 | % and binds the identifier to Slave. Peer is bound to the | |
266 | % IP-address of the client. | |
267 | ||
268 | %! tcp_connect(+SocketId, +HostAndPort) is det. | |
267 | % This predicate waits on a server socket for a connection request by | |
268 | % a client. On success, it creates a new socket for the client and | |
269 | % binds the identifier to Slave. Peer is bound to the IP-address of | |
270 | % the client or the atom `af_unix` if Socket is an AF_UNIX socket (see | |
271 | % unix_domain_socket/1). | |
272 | ||
273 | %! tcp_connect(+SocketId, +Address) is det. | |
269 | 274 | % |
270 | 275 | % Connect SocketId. After successful completion, tcp_open_socket/3 |
271 | 276 | % can be used to create I/O-Streams to the remote socket. This |
289 | 294 | % talk(StreamPair), |
290 | 295 | % close(StreamPair)) |
291 | 296 | % == |
297 | % | |
298 | % If SocketId is an AF_UNIX socket (see unix_domain_socket/1), Address | |
299 | % is an atom or string denoting a file name. | |
292 | 300 | |
293 | 301 | |
294 | 302 | /******************************* |
328 | 336 | %! tcp_connect(+Address, -StreamPair, +Options) is det. |
329 | 337 | %! tcp_connect(+Socket, +Address, -StreamPair) is det. |
330 | 338 | % |
331 | % Establish a TCP communication as a client. The +,-,+ mode is the | |
332 | % preferred way for a client to establish a connection. This | |
333 | % predicate can be hooked to support network proxies. To use a | |
334 | % proxy, the hook proxy_for_url/3 must be defined. Permitted | |
335 | % options are: | |
339 | % Establish a TCP communication as a client. The +,-,+ mode is the | |
340 | % preferred way for a client to establish a connection. This predicate | |
341 | % can be hooked to support network proxies. To use a proxy, the hook | |
342 | % proxy_for_url/3 must be defined. Permitted options are: | |
336 | 343 | % |
337 | 344 | % * bypass_proxy(+Boolean) |
338 | 345 | % Defaults to =false=. If =true=, do not attempt to use any |
342 | 349 | % Defaults to =false=. If =true=, set nodelay on the |
343 | 350 | % resulting socket using tcp_setopt(Socket, nodelay) |
344 | 351 | % |
345 | % The +,+,- mode is deprecated and does not support proxies. It | |
346 | % behaves like tcp_connect/4, but creates a stream pair (see | |
352 | % The +,+,- mode is deprecated and does not support proxies. It | |
353 | % behaves like tcp_connect/4, but creates a stream pair (see | |
347 | 354 | % stream_pair/3). |
348 | 355 | % |
349 | % @error proxy_error(tried(ResultList)) is raised by mode (+,-,+) | |
350 | % if proxies are defines by proxy_for_url/3 but no proxy can | |
351 | % establsh the connection. `ResultList` contains one or more terms | |
352 | % of the form false(Proxy) for a hook that simply failed or | |
353 | % error(Proxy, ErrorTerm) for a hook that raised an exception. | |
354 | % | |
355 | % @see library(http/http_proxy) defines a hook that allows to | |
356 | % connect through HTTP proxies that support the =CONNECT= method. | |
356 | % @arg Address is either a Host:Port term or a file name (atom or | |
357 | % string). The latter connects to an AF_UNIX socket and requires | |
358 | % unix_domain_socket/1. | |
359 | % | |
360 | % @error proxy_error(tried(ResultList)) is raised by mode (+,-,+) if | |
361 | % proxies are defines by proxy_for_url/3 but no proxy can establsh the | |
362 | % connection. `ResultList` contains one or more terms of the form | |
363 | % false(Proxy) for a hook that simply failed or error(Proxy, | |
364 | % ErrorTerm) for a hook that raised an exception. | |
365 | % | |
366 | % @see library(http/http_proxy) defines a hook that allows to connect | |
367 | % through HTTP proxies that support the =CONNECT= method. | |
357 | 368 | |
358 | 369 | % Main mode: +,-,+ |
359 | 370 | tcp_connect(Address, StreamPair, Options) :- |
386 | 397 | |
387 | 398 | |
388 | 399 | tcp_connect_direct(Address, Socket, StreamPair):- |
389 | tcp_socket(Socket), | |
400 | make_socket(Address, Socket), | |
390 | 401 | catch(tcp_connect(Socket, Address, StreamPair), |
391 | 402 | Error, |
392 | 403 | ( tcp_close_socket(Socket), |
393 | 404 | throw(Error) |
394 | 405 | )). |
406 | ||
407 | :- if(current_predicate(unix_domain_socket/1)). | |
408 | make_socket(Address, Socket) :- | |
409 | ( atom(Address) | |
410 | ; string(Address) | |
411 | ), | |
412 | !, | |
413 | unix_domain_socket(Socket). | |
414 | :- endif. | |
415 | make_socket(_Address, Socket) :- | |
416 | tcp_socket(Socket). | |
417 | ||
395 | 418 | |
396 | 419 | %! tcp_select(+ListOfStreams, -ReadyList, +TimeOut) |
397 | 420 | % |
0 | /* Part of SWI-Prolog | |
1 | ||
2 | Author: Jan Wielemaker | |
3 | E-mail: J.Wielemaker@vu.nl | |
4 | WWW: http://www.swi-prolog.org | |
5 | Copyright (c) 2020, VU University Amsterdam | |
6 | All rights reserved. | |
7 | ||
8 | Redistribution and use in source and binary forms, with or without | |
9 | modification, are permitted provided that the following conditions | |
10 | are met: | |
11 | ||
12 | 1. Redistributions of source code must retain the above copyright | |
13 | notice, this list of conditions and the following disclaimer. | |
14 | ||
15 | 2. Redistributions in binary form must reproduce the above copyright | |
16 | notice, this list of conditions and the following disclaimer in | |
17 | the documentation and/or other materials provided with the | |
18 | distribution. | |
19 | ||
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
23 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
24 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
25 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
26 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
28 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
29 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
30 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
31 | POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | :- module(test_af_unix, | |
35 | [ test_af_unix/0 | |
36 | ]). | |
37 | :- use_module(library(socket)). | |
38 | ||
39 | :- if(current_predicate(unix_domain_socket/1)). | |
40 | :- use_module(library(debug)). | |
41 | :- use_module(library(readutil)). | |
42 | ||
43 | test_af_unix :- | |
44 | tmp_file(af_unix, File), | |
45 | server(File, Tid), | |
46 | client(File), | |
47 | thread_signal(Tid, throw(stop)), | |
48 | thread_join(Tid, Status), | |
49 | assertion(Status == exception(stop)). | |
50 | ||
51 | server(File, Thread) :- | |
52 | ( access_file(File, exist) | |
53 | -> delete_file(File) | |
54 | ; true | |
55 | ), | |
56 | unix_domain_socket(S), | |
57 | tcp_bind(S, File), | |
58 | !, | |
59 | tcp_listen(S, 5), | |
60 | tcp_open_socket(S, AcceptFd, _), | |
61 | thread_create(dispatch(AcceptFd), Thread). | |
62 | ||
63 | dispatch(AcceptFd) :- | |
64 | tcp_accept(AcceptFd, Socket, Peer), | |
65 | thread_create(process_client(Socket, Peer), _, | |
66 | [ detached(true) | |
67 | ]), | |
68 | dispatch(AcceptFd). | |
69 | ||
70 | process_client(Socket, Peer) :- | |
71 | debug(af_unix, "Connected from ~p~n", [Peer]), | |
72 | setup_call_cleanup( | |
73 | tcp_open_socket(Socket, StreamPair), | |
74 | handle_service(StreamPair), | |
75 | close(StreamPair)). | |
76 | ||
77 | handle_service(Stream) :- | |
78 | read_line_to_string(Stream, String), | |
79 | format(Stream, '~s~n', [String]), | |
80 | flush_output(Stream), | |
81 | ( String == "bye" | |
82 | -> true | |
83 | ; handle_service(Stream) | |
84 | ). | |
85 | ||
86 | client(File) :- | |
87 | unix_domain_socket(Socket), | |
88 | tcp_connect(Socket, File), | |
89 | tcp_open_socket(Socket, Stream), | |
90 | ping(Stream, "Hello world"), | |
91 | ping(Stream, "bye"), | |
92 | close(Stream). | |
93 | ||
94 | ping(Stream, Data) :- | |
95 | format(Stream, '~s~n', [Data]), | |
96 | flush_output(Stream), | |
97 | read_line_to_string(Stream, Reply), | |
98 | assertion(Data == Reply). | |
99 | ||
100 | :- else. | |
101 | ||
102 | test_af_unix. | |
103 | ||
104 | :- endif. |
199 | 199 | |
200 | 200 | add_dependencies(doc.html ${pkg}.doc.html) |
201 | 201 | |
202 | set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Documentation) | |
202 | 203 | prepend(doc_files ${CMAKE_CURRENT_BINARY_DIR}/ ${pkg}.html ${vimages}) |
203 | 204 | install(FILES ${doc_files} |
204 | DESTINATION ${SWIPL_INSTALL_PREFIX}/doc/packages | |
205 | DESTINATION ${SWIPL_INSTALL_DOC}/packages | |
205 | 206 | COMPONENT Documentation |
206 | 207 | OPTIONAL) |
207 | 208 | endif(INSTALL_DOCUMENTATION) |
255 | 255 | endif() |
256 | 256 | endforeach() |
257 | 257 | |
258 | set(extdest ${SWIPL_INSTALL_PREFIX}/doc/packages/examples/${SWIPL_PKG}) | |
258 | set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Documentation) | |
259 | set(extdest ${SWIPL_INSTALL_DOC}/packages/examples/${SWIPL_PKG}) | |
259 | 260 | if(subdir) |
260 | 261 | set(extdest ${extdest}/${subdir}) |
261 | 262 | set(subdir_ ${subdir}_) |
318 | 319 | -t halt) |
319 | 320 | # Write db with lists of tests to be used with -DINSTALL_TESTS |
320 | 321 | if(INSTALL_TESTS) |
322 | set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Tests) | |
321 | 323 | file(RELATIVE_PATH rel_test_dir |
322 | 324 | ${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_SOURCE_DIR}) |
323 | 325 | file(APPEND ${INSTALL_TESTS_DB} |
22 | 22 | |
23 | 23 | if(HAVE_SOCKET) |
24 | 24 | AC_CHECK_HEADERS(sys/socket.h) |
25 | AC_CHECK_HEADERS(sys/un.h) | |
25 | 26 | if(HAVE_SYS_SOCKET_H) |
26 | 27 | set(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} sys/socket.h) |
27 | 28 | endif() |
6 | 6 | FILES SWI-cpp.h DESTINATION |
7 | 7 | ${SWIPL_INSTALL_INCLUDE}) |
8 | 8 | |
9 | swipl_examples(test.cpp likes.cpp likes.pl test.pl) | |
9 | swipl_examples(test.cpp likes.cpp likes.pl test.pl README.md) | |
10 | 10 | |
11 | 11 | pkg_doc( |
12 | 12 | pl2cpp |
0 | [Jul 21 2009] | |
1 | ||
2 | * MODIFIED: Make initialization/1 ISO compliant | |
3 | This patch is a modest cleanup to the implementation of '$load_file'/3 | |
4 | from init.pl and provides an ISO compatible implementation of | |
5 | initialization/1. This executes the argument goal *after* loading the | |
6 | file rather than when encountering the directive. Often this makes no | |
7 | difference, but notably load_foreign_library/1 is an exception. | |
8 | Therefore we added use_foreign_library/1,2 that act as a directive and | |
9 | provides proper integration with saved-states automatically. Loading | |
10 | code using initialization(load_foreign_library(...)) will load the | |
11 | library immediately and issue a warning. | |
12 | ||
13 | See initialization/1,2 for details and further hints for dealing with | |
14 | possible compatibility problems. | |
15 | ||
16 | [Jul 18 2009] | |
17 | ||
18 | * BUILD: Supported way to install using links instead of copying (developers) | |
19 | [Mar 19 2009] | |
20 | ||
21 | * CLEANUP: Removed all trailing whitespace from all source-files. This avoids many GIT (merge) warnings. | |
22 | [Dec 22 2008] | |
23 | ||
24 | * ADDED: C++ registration for non-deterministic predicates. Willem Robert van Hage. | |
25 | ||
26 | [Sep 11 2008] | |
27 | ||
28 | * PORT: Add AC_PREREQ to configure.h for systems that auto-select autoconf | |
29 | versions. After tip by Ulrich Neumerkel. | |
30 | ||
31 | [Aug 11 2008] | |
32 | ||
33 | * INSTALL: Remove all configure files from the git repository | |
34 | [Dec 18 2007] | |
35 | ||
36 | * FIXED: Handling of #define PROLOG_MODULE in the C++ interface. | |
37 | * MODIFIED: Note that the PlRegister() class has an extra argument for | |
38 | all initializers. | |
39 | Sep 25, 2007 | |
40 | ||
41 | * FIXED: Allow multiple inclusions. Mary Ellen Foster. | |
42 | ||
43 | Jan 18, 2007 | |
44 | ||
45 | * FIXED/MODIFIED: PlQuery(Module, Name, Args) now calls using Module | |
46 | as context. Christian Mol. | |
47 | ||
48 | Apr 11, 2004 | |
49 | ||
50 | * Fixed ambiguity in PlTermvDomainError constructor showing up with g++ | |
51 | 3.3. | |
52 | ||
53 | Jan 21, 2003 | |
54 | ||
55 | * One more const to avoid confusing the compiler. Thanks to Alan Baljeu | |
56 | and Fabien Todescato. | |
57 | ||
58 | Jan 12, 2003 | |
59 | ||
60 | * Patches by Alan Baljeu, adding many const declarations to the interface. | |
61 | ||
62 | VERSION 1.0.4 | |
63 | ============= | |
64 | ||
65 | * ADDED: Destructor to PlEngine class, calling PL_cleanup(). Requires | |
66 | SWI-Prolog 3.4.1 or later. | |
67 | ||
68 | VERSION 1.0.3 | |
69 | ============= | |
70 | ||
71 | * FIXED: untyped 'operator =' declarations reported by gcc version 2.95.2. | |
72 | ||
73 | VERSION 1.0.2 | |
74 | ============= | |
75 | ||
76 | * FIXED: PlException to pass exceptions other then domain and type errors | |
77 | correctly. Thanks to Use Lesta. | |
78 | ||
79 | VERSION 1.0.1 | |
80 | ============= | |
81 | ||
82 | * ADDED: conversion between PlTerm and void* | |
83 | ||
84 | ||
85 | VERSION 1.0.0 | |
86 | ============= |
0 | SWI-Prolog C++ interface | |
1 | ||
2 | Demo: make (must be GNU-make) produces | |
3 | ||
4 | * embedded program likes. See likes.cpp | |
5 | * test.so, load using test.pl holding the examples from | |
6 | the manual and some more. | |
7 | ||
8 | Note: I'm an amateur C++ programmer. Volker Wysk <post@volker-wysk.de> | |
9 | has compiled a new C++ interface and announced it for | |
10 | first public testing on January 14, 2002. This interface | |
11 | may be downloaded from. | |
12 | ||
13 | http://www.volker-wysk.de/swiprolog-c++/index.html |
0 | # SWI-Prolog C++ interface | |
1 | ||
2 | ## Embedding SWI-Prolog in a C++ program | |
3 | ||
4 | The files likes.pl and likes.cpp provide a simple example emedding | |
5 | SWI-Prolog. To compile, run | |
6 | ||
7 | swipl-ld -o likes likes.cpp likes.pl | |
8 | ||
9 | Next, run as e.g. | |
10 | ||
11 | ./likes john | |
12 | ./likes -happy | |
13 | ||
14 | ## Extending SWI-Prolog using C++ code | |
15 | ||
16 | The files `test.pl` and `test.cpp` add foreign predicates to SWI-Prolog. | |
17 | To compile, run | |
18 | ||
19 | swipl-ld -o test -shared test.cpp | |
20 | ||
21 | Next, run as e.g. | |
22 | ||
23 | swipl test.pl | |
24 | ?- hello(world). | |
25 | Hello world | |
26 | true. |
0 | #!/bin/sh | |
1 | # | |
2 | # install - install a program, script, or datafile | |
3 | # This comes from X11R5. | |
4 | # | |
5 | # Calling this script install-sh is preferred over install.sh, to prevent | |
6 | # `make' implicit rules from creating a file called install from it | |
7 | # when there is no Makefile. | |
8 | # | |
9 | # This script is compatible with the BSD install script, but was written | |
10 | # from scratch. | |
11 | # | |
12 | ||
13 | ||
14 | # set DOITPROG to echo to test this script | |
15 | ||
16 | # Don't use :- since 4.3BSD and earlier shells don't like it. | |
17 | doit="${DOITPROG-}" | |
18 | ||
19 | ||
20 | # put in absolute paths if you don't have them in your path; or use env. vars. | |
21 | ||
22 | mvprog="${MVPROG-mv}" | |
23 | cpprog="${CPPROG-cp}" | |
24 | chmodprog="${CHMODPROG-chmod}" | |
25 | chownprog="${CHOWNPROG-chown}" | |
26 | chgrpprog="${CHGRPPROG-chgrp}" | |
27 | stripprog="${STRIPPROG-strip}" | |
28 | rmprog="${RMPROG-rm}" | |
29 | mkdirprog="${MKDIRPROG-mkdir}" | |
30 | ||
31 | tranformbasename="" | |
32 | transform_arg="" | |
33 | instcmd="$mvprog" | |
34 | chmodcmd="$chmodprog 0755" | |
35 | chowncmd="" | |
36 | chgrpcmd="" | |
37 | stripcmd="" | |
38 | rmcmd="$rmprog -f" | |
39 | mvcmd="$mvprog" | |
40 | src="" | |
41 | dst="" | |
42 | dir_arg="" | |
43 | ||
44 | while [ x"$1" != x ]; do | |
45 | case $1 in | |
46 | -c) instcmd="$cpprog" | |
47 | shift | |
48 | continue;; | |
49 | ||
50 | -d) dir_arg=true | |
51 | shift | |
52 | continue;; | |
53 | ||
54 | -m) chmodcmd="$chmodprog $2" | |
55 | shift | |
56 | shift | |
57 | continue;; | |
58 | ||
59 | -o) chowncmd="$chownprog $2" | |
60 | shift | |
61 | shift | |
62 | continue;; | |
63 | ||
64 | -g) chgrpcmd="$chgrpprog $2" | |
65 | shift | |
66 | shift | |
67 | continue;; | |
68 | ||
69 | -s) stripcmd="$stripprog" | |
70 | shift | |
71 | continue;; | |
72 | ||
73 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` | |
74 | shift | |
75 | continue;; | |
76 | ||
77 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` | |
78 | shift | |
79 | continue;; | |
80 | ||
81 | *) if [ x"$src" = x ] | |
82 | then | |
83 | src=$1 | |
84 | else | |
85 | # this colon is to work around a 386BSD /bin/sh bug | |
86 | : | |
87 | dst=$1 | |
88 | fi | |
89 | shift | |
90 | continue;; | |
91 | esac | |
92 | done | |
93 | ||
94 | if [ x"$src" = x ] | |
95 | then | |
96 | echo "install: no input file specified" | |
97 | exit 1 | |
98 | else | |
99 | true | |
100 | fi | |
101 | ||
102 | if [ x"$dir_arg" != x ]; then | |
103 | dst=$src | |
104 | src="" | |
105 | ||
106 | if [ -d $dst ]; then | |
107 | instcmd=: | |
108 | else | |
109 | instcmd=mkdir | |
110 | fi | |
111 | else | |
112 | ||
113 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command | |
114 | # might cause directories to be created, which would be especially bad | |
115 | # if $src (and thus $dsttmp) contains '*'. | |
116 | ||
117 | if [ -f $src -o -d $src ] | |
118 | then | |
119 | true | |
120 | else | |
121 | echo "install: $src does not exist" | |
122 | exit 1 | |
123 | fi | |
124 | ||
125 | if [ x"$dst" = x ] | |
126 | then | |
127 | echo "install: no destination specified" | |
128 | exit 1 | |
129 | else | |
130 | true | |
131 | fi | |
132 | ||
133 | # If destination is a directory, append the input filename; if your system | |
134 | # does not like double slashes in filenames, you may need to add some logic | |
135 | ||
136 | if [ -d $dst ] | |
137 | then | |
138 | dst="$dst"/`basename $src` | |
139 | else | |
140 | true | |
141 | fi | |
142 | fi | |
143 | ||
144 | ## this sed command emulates the dirname command | |
145 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | |
146 | ||
147 | # Make sure that the destination directory exists. | |
148 | # this part is taken from Noah Friedman's mkinstalldirs script | |
149 | ||
150 | # Skip lots of stat calls in the usual case. | |
151 | if [ ! -d "$dstdir" ]; then | |
152 | defaultIFS=' | |
153 | ' | |
154 | IFS="${IFS-${defaultIFS}}" | |
155 | ||
156 | oIFS="${IFS}" | |
157 | # Some sh's can't handle IFS=/ for some reason. | |
158 | IFS='%' | |
159 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` | |
160 | IFS="${oIFS}" | |
161 | ||
162 | pathcomp='' | |
163 | ||
164 | while [ $# -ne 0 ] ; do | |
165 | pathcomp="${pathcomp}${1}" | |
166 | shift | |
167 | ||
168 | if [ ! -d "${pathcomp}" ] ; | |
169 | then | |
170 | $mkdirprog "${pathcomp}" | |
171 | else | |
172 | true | |
173 | fi | |
174 | ||
175 | pathcomp="${pathcomp}/" | |
176 | done | |
177 | fi | |
178 | ||
179 | if [ x"$dir_arg" != x ] | |
180 | then | |
181 | $doit $instcmd $dst && | |
182 | ||
183 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && | |
184 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && | |
185 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && | |
186 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi | |
187 | else | |
188 | ||
189 | # If we're going to rename the final executable, determine the name now. | |
190 | ||
191 | if [ x"$transformarg" = x ] | |
192 | then | |
193 | dstfile=`basename $dst` | |
194 | else | |
195 | dstfile=`basename $dst $transformbasename | | |
196 | sed $transformarg`$transformbasename | |
197 | fi | |
198 | ||
199 | # don't allow the sed command to completely eliminate the filename | |
200 | ||
201 | if [ x"$dstfile" = x ] | |
202 | then | |
203 | dstfile=`basename $dst` | |
204 | else | |
205 | true | |
206 | fi | |
207 | ||
208 | # Make a temp file name in the proper directory. | |
209 | ||
210 | dsttmp=$dstdir/#inst.$$# | |
211 | ||
212 | # Move or copy the file name to the temp name | |
213 | ||
214 | $doit $instcmd $src $dsttmp && | |
215 | ||
216 | trap "rm -f ${dsttmp}" 0 && | |
217 | ||
218 | # and set any options; do chmod last to preserve setuid bits | |
219 | ||
220 | # If any of these fail, we abort the whole thing. If we want to | |
221 | # ignore errors from any of these, just make sure not to ignore | |
222 | # errors from the above "$doit $instcmd $src $dsttmp" command. | |
223 | ||
224 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && | |
225 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && | |
226 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && | |
227 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && | |
228 | ||
229 | # Now rename the file to the real destination. | |
230 | ||
231 | $doit $rmcmd -f $dstdir/$dstfile && | |
232 | $doit $mvcmd $dsttmp $dstdir/$dstfile | |
233 | ||
234 | fi && | |
235 | ||
236 | ||
237 | exit 0 |
0 | #!/bin/sh | |
1 | # | |
2 | # install - install a program, script, or datafile | |
3 | # This comes from X11R5. | |
4 | # | |
5 | # Calling this script install-sh is preferred over install.sh, to prevent | |
6 | # `make' implicit rules from creating a file called install from it | |
7 | # when there is no Makefile. | |
8 | # | |
9 | # This script is compatible with the BSD install script, but was written | |
10 | # from scratch. | |
11 | # | |
12 | ||
13 | ||
14 | # set DOITPROG to echo to test this script | |
15 | ||
16 | # Don't use :- since 4.3BSD and earlier shells don't like it. | |
17 | doit="${DOITPROG-}" | |
18 | ||
19 | ||
20 | # put in absolute paths if you don't have them in your path; or use env. vars. | |
21 | ||
22 | mvprog="${MVPROG-mv}" | |
23 | cpprog="${CPPROG-cp}" | |
24 | chmodprog="${CHMODPROG-chmod}" | |
25 | chownprog="${CHOWNPROG-chown}" | |
26 | chgrpprog="${CHGRPPROG-chgrp}" | |
27 | stripprog="${STRIPPROG-strip}" | |
28 | rmprog="${RMPROG-rm}" | |
29 | mkdirprog="${MKDIRPROG-mkdir}" | |
30 | ||
31 | tranformbasename="" | |
32 | transform_arg="" | |
33 | instcmd="$mvprog" | |
34 | chmodcmd="$chmodprog 0755" | |
35 | chowncmd="" | |
36 | chgrpcmd="" | |
37 | stripcmd="" | |
38 | rmcmd="$rmprog -f" | |
39 | mvcmd="$mvprog" | |
40 | src="" | |
41 | dst="" | |
42 | dir_arg="" | |
43 | ||
44 | while [ x"$1" != x ]; do | |
45 | case $1 in | |
46 | -c) instcmd="$cpprog" | |
47 | shift | |
48 | continue;; | |
49 | ||
50 | -d) dir_arg=true | |
51 | shift | |
52 | continue;; | |
53 | ||
54 | -m) chmodcmd="$chmodprog $2" | |
55 | shift | |
56 | shift | |
57 | continue;; | |
58 | ||
59 | -o) chowncmd="$chownprog $2" | |
60 | shift | |
61 | shift | |
62 | continue;; | |
63 | ||
64 | -g) chgrpcmd="$chgrpprog $2" | |
65 | shift | |
66 | shift | |
67 | continue;; | |
68 | ||
69 | -s) stripcmd="$stripprog" | |
70 | shift | |
71 | continue;; | |
72 | ||
73 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` | |
74 | shift | |
75 | continue;; | |
76 | ||
77 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` | |
78 | shift | |
79 | continue;; | |
80 | ||
81 | *) if [ x"$src" = x ] | |
82 | then | |
83 | src=$1 | |
84 | else | |
85 | # this colon is to work around a 386BSD /bin/sh bug | |
86 | : | |
87 | dst=$1 | |
88 | fi | |
89 | shift | |
90 | continue;; | |
91 | esac | |
92 | done | |
93 | ||
94 | if [ x"$src" = x ] | |
95 | then | |
96 | echo "install: no input file specified" | |
97 | exit 1 | |
98 | else | |
99 | true | |
100 | fi | |
101 | ||
102 | if [ x"$dir_arg" != x ]; then | |
103 | dst=$src | |
104 | src="" | |
105 | ||
106 | if [ -d $dst ]; then | |
107 | instcmd=: | |
108 | else | |
109 | instcmd=mkdir | |
110 | fi | |
111 | else | |
112 | ||
113 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command | |
114 | # might cause directories to be created, which would be especially bad | |
115 | # if $src (and thus $dsttmp) contains '*'. | |
116 | ||
117 | if [ -f $src -o -d $src ] | |
118 | then | |
119 | true | |
120 | else | |
121 | echo "install: $src does not exist" | |
122 | exit 1 | |
123 | fi | |
124 | ||
125 | if [ x"$dst" = x ] | |
126 | then | |
127 | echo "install: no destination specified" | |
128 | exit 1 | |
129 | else | |
130 | true | |
131 | fi | |
132 | ||
133 | # If destination is a directory, append the input filename; if your system | |
134 | # does not like double slashes in filenames, you may need to add some logic | |
135 | ||
136 | if [ -d $dst ] | |
137 | then | |
138 | dst="$dst"/`basename $src` | |
139 | else | |
140 | true | |
141 | fi | |
142 | fi | |
143 | ||
144 | ## this sed command emulates the dirname command | |
145 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | |
146 | ||
147 | # Make sure that the destination directory exists. | |
148 | # this part is taken from Noah Friedman's mkinstalldirs script | |
149 | ||
150 | # Skip lots of stat calls in the usual case. | |
151 | if [ ! -d "$dstdir" ]; then | |
152 | defaultIFS=' | |
153 | ' | |
154 | IFS="${IFS-${defaultIFS}}" | |
155 | ||
156 | oIFS="${IFS}" | |
157 | # Some sh's can't handle IFS=/ for some reason. | |
158 | IFS='%' | |
159 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` | |
160 | IFS="${oIFS}" | |
161 | ||
162 | pathcomp='' | |
163 | ||
164 | while [ $# -ne 0 ] ; do | |
165 | pathcomp="${pathcomp}${1}" | |
166 | shift | |
167 | ||
168 | if [ ! -d "${pathcomp}" ] ; | |
169 | then | |
170 | $mkdirprog "${pathcomp}" | |
171 | else | |
172 | true | |
173 | fi | |
174 | ||
175 | pathcomp="${pathcomp}/" | |
176 | done | |
177 | fi | |
178 | ||
179 | if [ x"$dir_arg" != x ] | |
180 | then | |
181 | $doit $instcmd $dst && | |
182 | ||
183 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && | |
184 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && | |
185 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && | |
186 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi | |
187 | else | |
188 | ||
189 | # If we're going to rename the final executable, determine the name now. | |
190 | ||
191 | if [ x"$transformarg" = x ] | |
192 | then | |
193 | dstfile=`basename $dst` | |
194 | else | |
195 | dstfile=`basename $dst $transformbasename | | |
196 | sed $transformarg`$transformbasename | |
197 | fi | |
198 | ||
199 | # don't allow the sed command to completely eliminate the filename | |
200 | ||
201 | if [ x"$dstfile" = x ] | |
202 | then | |
203 | dstfile=`basename $dst` | |
204 | else | |
205 | true | |
206 | fi | |
207 | ||
208 | # Make a temp file name in the proper directory. | |
209 | ||
210 | dsttmp=$dstdir/#inst.$$# | |
211 | ||
212 | # Move or copy the file name to the temp name | |
213 | ||
214 | $doit $instcmd $src $dsttmp && | |
215 | ||
216 | trap "rm -f ${dsttmp}" 0 && | |
217 | ||
218 | # and set any options; do chmod last to preserve setuid bits | |
219 | ||
220 | # If any of these fail, we abort the whole thing. If we want to | |
221 | # ignore errors from any of these, just make sure not to ignore | |
222 | # errors from the above "$doit $instcmd $src $dsttmp" command. | |
223 | ||
224 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && | |
225 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && | |
226 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && | |
227 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && | |
228 | ||
229 | # Now rename the file to the real destination. | |
230 | ||
231 | $doit $rmcmd -f $dstdir/$dstfile && | |
232 | $doit $mvcmd $dsttmp $dstdir/$dstfile | |
233 | ||
234 | fi && | |
235 | ||
236 | ||
237 | exit 0 |
110 | 110 | PACKAGES clib sgml plunit ssl zlib |
111 | 111 | PARENT_LIB) |
112 | 112 | |
113 | if(INSTALL_TESTS) | |
114 | install(FILES examples/demo_body.pl | |
115 | DESTINATION ${INSTALL_TESTS_DIR}/packages/http/examples) | |
113 | has_package(ssl, HAVE_SSL_PACKAGE) | |
114 | if(HAVE_SSL_PACKAGE) | |
115 | set(doc_depends ssl) | |
116 | 116 | endif() |
117 | 117 | |
118 | 118 | pkg_doc(http |
120 | 120 | http |
121 | 121 | SOURCES |
122 | 122 | json.md |
123 | SOURCE post.md --lib=http/html_write | |
123 | SOURCE | |
124 | post.md --lib=http/html_write | |
125 | DEPENDS | |
126 | ${doc_depends} | |
124 | 127 | SECTION |
125 | 128 | websocket.pl hub.pl |
126 | 129 | SUBSECTION |
1853 | 1853 | { base64(Data, DataBase64), |
1854 | 1854 | atom_codes(DataBase64, Codes) |
1855 | 1855 | }, |
1856 | string(Codes), "\r\n". | |
1856 | string(Codes). | |
1857 | 1857 | auth_field_value(negotiate) --> |
1858 | "Negotiate\r\n". | |
1858 | "Negotiate". | |
1859 | 1859 | auth_field_value(basic) --> |
1860 | 1860 | !, |
1861 | "Basic\r\n". | |
1861 | "Basic". | |
1862 | 1862 | auth_field_value(basic(Realm)) --> |
1863 | "Basic Realm=\"", atom(Realm), "\"\r\n". | |
1863 | "Basic Realm=\"", atom(Realm), "\"". | |
1864 | 1864 | auth_field_value(digest) --> |
1865 | 1865 | !, |
1866 | "Digest\r\n". | |
1866 | "Digest". | |
1867 | 1867 | auth_field_value(digest(Details)) --> |
1868 | "Digest ", atom(Details), "\r\n". | |
1868 | "Digest ", atom(Details). | |
1869 | 1869 | |
1870 | 1870 | %! value_options(+List, +Field)// |
1871 | 1871 | % |
61 | 61 | :- autoload(library(http/http_header), |
62 | 62 | [ http_parse_header/2, http_post_data/3 ]). |
63 | 63 | :- autoload(library(http/http_stream),[stream_range_open/3]). |
64 | :- if(exists_source(library(ssl))). | |
64 | :- if(( exists_source(library(ssl)), | |
65 | \+ current_prolog_flag(pldoc_to_tex,true))). | |
65 | 66 | :- autoload(library(ssl), [ssl_upgrade_legacy_options/2]). |
66 | 67 | :- endif. |
67 | 68 |
53 | 53 | :- use_module(library(main)). |
54 | 54 | :- use_module(library(readutil)). |
55 | 55 | |
56 | :- if(exists_source(library(http/http_ssl_plugin))). | |
56 | :- if(( exists_source(library(http/http_ssl_plugin)), | |
57 | \+ current_prolog_flag(pldoc_to_tex,true))). | |
57 | 58 | :- use_module(library(ssl)). |
58 | 59 | :- use_module(library(http/http_ssl_plugin)). |
59 | 60 | :- endif. |
826 | 827 | repeat, |
827 | 828 | State = deadline(Count), |
828 | 829 | Deadline is FirstDeadline+Count*Interval, |
829 | ( thread_get_message(Me, Msg, [deadline(Deadline)]) | |
830 | ( thread_idle(thread_get_message(Me, Msg, [deadline(Deadline)]), | |
831 | long) | |
830 | 832 | -> catch(ignore(handle_message(Msg)), E, |
831 | 833 | print_message(error, E)), |
832 | 834 | Msg == quit, |
840 | 842 | wait(_) :- |
841 | 843 | thread_self(Me), |
842 | 844 | repeat, |
843 | thread_get_message(Me, Msg), | |
845 | thread_idle(thread_get_message(Me, Msg), long), | |
844 | 846 | catch(ignore(handle_message(Msg)), E, |
845 | 847 | print_message(error, E)), |
846 | 848 | Msg == quit, |
581 | 581 | option(queue(Queue), Options), |
582 | 582 | option(max_idle_time(MaxIdle), Options, infinite), |
583 | 583 | repeat, |
584 | garbage_collect, | |
585 | trim_stacks, | |
584 | thread_idle(get_work(Queue, Message, MaxIdle), long), | |
586 | 585 | debug(http(worker), 'Waiting for a job ...', []), |
587 | ( MaxIdle == infinite | |
588 | -> thread_get_message(Queue, Message) | |
589 | ; thread_get_message(Queue, Message, [timeout(MaxIdle)]) | |
590 | -> true | |
591 | ; Message = quit(idle) | |
592 | ), | |
593 | 586 | debug(http(worker), 'Got job ~p', [Message]), |
594 | 587 | ( Message = quit(Sender) |
595 | 588 | -> !, |
617 | 610 | ) |
618 | 611 | ). |
619 | 612 | |
613 | get_work(Queue, Message, infinite) :- | |
614 | !, | |
615 | thread_get_message(Queue, Message). | |
616 | get_work(Queue, Message, MaxIdle) :- | |
617 | ( thread_get_message(Queue, Message, [timeout(MaxIdle)]) | |
618 | -> true | |
619 | ; Message = quit(idle) | |
620 | ). | |
621 | ||
620 | 622 | |
621 | 623 | %! open_client(+Message, +Queue, -Goal, -In, -Out, |
622 | 624 | %! +Options, -ClientOptions) is semidet. |
0 | SWI-Prolog INCLP(R) | |
1 | ------------------- | |
2 | ||
3 | Author: Leslie De Koninck, K.U.Leuven | |
4 | ||
5 | This software is a Constraint Logic Programming library, capable of | |
6 | solving nonlinear (polynomial) constraints over the real numbers. It is | |
7 | based on interval arithmetic techniques and is built on top of the | |
8 | K.U.Leuven CHR implementation which is also part of SWI-Prolog. The | |
9 | software is released with permission from the author under the standard | |
10 | SWI-Prolog license schema: GPL-2 + statement to allow linking with | |
11 | proprietary software. | |
12 | ||
13 | The sources of this package are maintained in packages/inclpr in the | |
14 | SWI-Prolog source distribution. The documentation source is in | |
15 | man/lib/inclpr.doc as part of the overall SWI-Prolog documentation. | |
16 | ||
17 | More information on INCLP(R) can be found at | |
18 | ||
19 | http://www.cs.kuleuven.be/~leslie/INCLPR/ | |
20 | ||
21 |
0 | SWI-Prolog INCLP(R) | |
1 | ------------------- | |
2 | ||
3 | Author: Leslie De Koninck, K.U.Leuven | |
4 | ||
5 | This software is a Constraint Logic Programming library, capable of | |
6 | solving nonlinear (polynomial) constraints over the real numbers. It is | |
7 | based on interval arithmetic techniques and is built on top of the | |
8 | K.U.Leuven CHR implementation which is also part of SWI-Prolog. The | |
9 | software is released with permission from the author under the standard | |
10 | SWI-Prolog license schema: GPL-2 + statement to allow linking with | |
11 | proprietary software. | |
12 | ||
13 | The sources of this package are maintained in packages/inclpr in the | |
14 | SWI-Prolog source distribution. The documentation source is in | |
15 | man/lib/inclpr.doc as part of the overall SWI-Prolog documentation. | |
16 | ||
17 | More information on INCLP(R) can be found at | |
18 | ||
19 | http://www.cs.kuleuven.be/~leslie/INCLPR/ | |
20 | ||
21 |
0 | #!/bin/sh | |
1 | # | |
2 | # install - install a program, script, or datafile | |
3 | # This comes from X11R5. | |
4 | # | |
5 | # Calling this script install-sh is preferred over install.sh, to prevent | |
6 | # `make' implicit rules from creating a file called install from it | |
7 | # when there is no Makefile. | |
8 | # | |
9 | # This script is compatible with the BSD install script, but was written | |
10 | # from scratch. | |
11 | # | |
12 | ||
13 | ||
14 | # set DOITPROG to echo to test this script | |
15 | ||
16 | # Don't use :- since 4.3BSD and earlier shells don't like it. | |
17 | doit="${DOITPROG-}" | |
18 | ||
19 | ||
20 | # put in absolute paths if you don't have them in your path; or use env. vars. | |
21 | ||
22 | mvprog="${MVPROG-mv}" | |
23 | cpprog="${CPPROG-cp}" | |
24 | chmodprog="${CHMODPROG-chmod}" | |
25 | chownprog="${CHOWNPROG-chown}" | |
26 | chgrpprog="${CHGRPPROG-chgrp}" | |
27 | stripprog="${STRIPPROG-strip}" | |
28 | rmprog="${RMPROG-rm}" | |
29 | mkdirprog="${MKDIRPROG-mkdir}" | |
30 | ||
31 | tranformbasename="" | |
32 | transform_arg="" | |
33 | instcmd="$mvprog" | |
34 | chmodcmd="$chmodprog 0755" | |
35 | chowncmd="" | |
36 | chgrpcmd="" | |
37 | stripcmd="" | |
38 | rmcmd="$rmprog -f" | |
39 | mvcmd="$mvprog" | |
40 | src="" | |
41 | dst="" | |
42 | dir_arg="" | |
43 | ||
44 | while [ x"$1" != x ]; do | |
45 | case $1 in | |
46 | -c) instcmd="$cpprog" | |
47 | shift | |
48 | continue;; | |
49 | ||
50 | -d) dir_arg=true | |
51 | shift | |
52 | continue;; | |
53 | ||
54 | -m) chmodcmd="$chmodprog $2" | |
55 | shift | |
56 | shift | |
57 | continue;; | |
58 | ||
59 | -o) chowncmd="$chownprog $2" | |
60 | shift | |
61 | shift | |
62 | continue;; | |
63 | ||
64 | -g) chgrpcmd="$chgrpprog $2" | |
65 | shift | |
66 | shift | |
67 | continue;; | |
68 | ||
69 | -s) stripcmd="$stripprog" | |
70 | shift | |
71 | continue;; | |
72 | ||
73 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` | |
74 | shift | |
75 | continue;; | |
76 | ||
77 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` | |
78 | shift | |
79 | continue;; | |
80 | ||
81 | *) if [ x"$src" = x ] | |
82 | then | |
83 | src=$1 | |
84 | else | |
85 | # this colon is to work around a 386BSD /bin/sh bug | |
86 | : | |
87 | dst=$1 | |
88 | fi | |
89 | shift | |
90 | continue;; | |
91 | esac | |
92 | done | |
93 | ||
94 | if [ x"$src" = x ] | |
95 | then | |
96 | echo "install: no input file specified" | |
97 | exit 1 | |
98 | else | |
99 | true | |
100 | fi | |
101 | ||
102 | if [ x"$dir_arg" != x ]; then | |
103 | dst=$src | |
104 | src="" | |
105 | ||
106 | if [ -d $dst ]; then | |
107 | instcmd=: | |
108 | else | |
109 | instcmd=mkdir | |
110 | fi | |
111 | else | |
112 | ||
113 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command | |
114 | # might cause directories to be created, which would be especially bad | |
115 | # if $src (and thus $dsttmp) contains '*'. | |
116 | ||
117 | if [ -f $src -o -d $src ] | |
118 | then | |
119 | true | |
120 | else | |
121 | echo "install: $src does not exist" | |
122 | exit 1 | |
123 | fi | |
124 | ||
125 | if [ x"$dst" = x ] | |
126 | then | |
127 | echo "install: no destination specified" | |
128 | exit 1 | |
129 | else | |
130 | true | |
131 | fi | |
132 | ||
133 | # If destination is a directory, append the input filename; if your system | |
134 | # does not like double slashes in filenames, you may need to add some logic | |
135 | ||
136 | if [ -d $dst ] | |
137 | then | |
138 | dst="$dst"/`basename $src` | |
139 | else | |
140 | true | |
141 | fi | |
142 | fi | |
143 | ||
144 | ## this sed command emulates the dirname command | |
145 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | |
146 | ||
147 | # Make sure that the destination directory exists. | |
148 | # this part is taken from Noah Friedman's mkinstalldirs script | |
149 | ||
150 | # Skip lots of stat calls in the usual case. | |
151 | if [ ! -d "$dstdir" ]; then | |
152 | defaultIFS=' | |
153 | ' | |
154 | IFS="${IFS-${defaultIFS}}" | |
155 | ||
156 | oIFS="${IFS}" | |
157 | # Some sh's can't handle IFS=/ for some reason. | |
158 | IFS='%' | |
159 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` | |
160 | IFS="${oIFS}" | |
161 | ||
162 | pathcomp='' | |
163 | ||
164 | while [ $# -ne 0 ] ; do | |
165 | pathcomp="${pathcomp}${1}" | |
166 | shift | |
167 | ||
168 | if [ ! -d "${pathcomp}" ] ; | |
169 | then | |
170 | $mkdirprog "${pathcomp}" | |
171 | else | |
172 | true | |
173 | fi | |
174 | ||
175 | pathcomp="${pathcomp}/" | |
176 | done | |
177 | fi | |
178 | ||
179 | if [ x"$dir_arg" != x ] | |
180 | then | |
181 | $doit $instcmd $dst && | |
182 | ||
183 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && | |
184 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && | |
185 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && | |
186 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi | |
187 | else | |
188 | ||
189 | # If we're going to rename the final executable, determine the name now. | |
190 | ||
191 | if [ x"$transformarg" = x ] | |
192 | then | |
193 | dstfile=`basename $dst` | |
194 | else | |
195 | dstfile=`basename $dst $transformbasename | | |
196 | sed $transformarg`$transformbasename | |
197 | fi | |
198 | ||
199 | # don't allow the sed command to completely eliminate the filename | |
200 | ||
201 | if [ x"$dstfile" = x ] | |
202 | then | |
203 | dstfile=`basename $dst` | |
204 | else | |
205 | true | |
206 | fi | |
207 | ||
208 | # Make a temp file name in the proper directory. | |
209 | ||
210 | dsttmp=$dstdir/#inst.$$# | |
211 | ||
212 | # Move or copy the file name to the temp name | |
213 | ||
214 | $doit $instcmd $src $dsttmp && | |
215 | ||
216 | trap "rm -f ${dsttmp}" 0 && | |
217 | ||
218 | # and set any options; do chmod last to preserve setuid bits | |
219 | ||
220 | # If any of these fail, we abort the whole thing. If we want to | |
221 | # ignore errors from any of these, just make sure not to ignore | |
222 | # errors from the above "$doit $instcmd $src $dsttmp" command. | |
223 | ||
224 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && | |
225 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && | |
226 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && | |
227 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && | |
228 | ||
229 | # Now rename the file to the real destination. | |
230 | ||
231 | $doit $rmcmd -f $dstdir/$dstfile && | |
232 | $doit $mvcmd $dsttmp $dstdir/$dstfile | |
233 | ||
234 | fi && | |
235 | ||
236 | ||
237 | exit 0 |
135 | 135 | |
136 | 136 | if(INSTALL_TESTS) |
137 | 137 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/src/java/jpltest.jar |
138 | DESTINATION ${INSTALL_TESTS_DIR}/packages/jpl/src/java) | |
138 | DESTINATION ${INSTALL_TESTS_DIR}/packages/jpl/src/java | |
139 | COMPONENT Tests) | |
139 | 140 | endif() |
140 | 141 | |
141 | 142 | else(JUNIT_JAR) |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1997-2018, University of Amsterdam | |
5 | Copyright (c) 1997-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | CWI, Amsterdam |
8 | 8 | All rights reserved. |
58 | 58 | clean_tt/2, % +Raw, -Clean |
59 | 59 | op(100, fx, #) |
60 | 60 | ]). |
61 | :- use_module(library(quintus)). | |
62 | :- use_module(library(filesex)). | |
63 | :- use_module(library(option)). | |
64 | :- use_module(library(apply)). | |
61 | :- autoload(library(apply),[maplist/3]). | |
62 | :- autoload(library(backcomp),[convert_time/8]). | |
63 | :- autoload(library(ctypes), | |
64 | [is_lower/1,to_upper/2,is_alpha/1,is_upper/1,to_lower/2]). | |
65 | :- autoload(library(debug),[debug/3]). | |
66 | :- autoload(library(filesex),[copy_file/2,directory_file_path/3]). | |
67 | :- autoload(library(gui_tracer),[gtrace/0]). | |
68 | :- autoload(library(lists), | |
69 | [ reverse/2, | |
70 | member/2, | |
71 | flatten/2, | |
72 | append/3, | |
73 | select/3, | |
74 | nth1/3, | |
75 | last/2 | |
76 | ]). | |
77 | :- autoload(library(main),[main/0,argv_options/3]). | |
78 | :- autoload(library(occurs),[sub_term/2]). | |
79 | :- autoload(library(option),[option/2,select_option/3]). | |
80 | :- autoload(library(readutil),[read_file_to_codes/3]). | |
81 | :- autoload(library(statistics),[statistics/0]). | |
65 | 82 | |
66 | 83 | ltx2htm_version('0.98'). % for SWI-Prolog 5.6.18 |
67 | 84 | |
1236 | 1253 | cmd(rightline({Tex}), #right(+Tex)). |
1237 | 1254 | |
1238 | 1255 | cmd(email({Address}), #url(URL, Address)) :- |
1239 | sformat(URL, 'mailto:~w', [Address]). | |
1256 | format(string(URL), 'mailto:~w', [Address]). | |
1240 | 1257 | cmd(url({Address}), #url(Address, Address)). |
1241 | 1258 | cmd(href({URL}, {Text}), #url(URL, +Text)). |
1242 | 1259 | cmd(file({File}), #tt(File)). |
1343 | 1360 | ps_extension(Ext), |
1344 | 1361 | file_base_name(Base, GifBase), |
1345 | 1362 | file_name_extension(GifBase, gif, GifFile), |
1346 | sformat(Img, '<img src="~w">', GifFile), | |
1363 | format(string(Img), '<img src="~w">', GifFile), | |
1347 | 1364 | make_output_directory, |
1348 | 1365 | html_output_dir(Dir), |
1349 | 1366 | atomic_list_concat([Dir, '/', GifFile], OutFile), |
1371 | 1388 | img_extension(Ext), |
1372 | 1389 | !, |
1373 | 1390 | file_base_name(AbsImgFile, ImgFile), |
1374 | sformat(Img, '<img src="~w">', ImgFile), | |
1391 | format(string(Img), '<img src="~w">', ImgFile), | |
1375 | 1392 | make_output_directory, |
1376 | 1393 | html_output_dir(Dir), |
1377 | 1394 | atomic_list_concat([Dir, '/', ImgFile], OutFile), |
1390 | 1407 | file_name_extension(Base, Ext, PsFile), |
1391 | 1408 | file_base_name(Base, GifBase), |
1392 | 1409 | file_name_extension(GifBase, gif, GifFile), |
1393 | sformat(Img, '<img src="~w">', GifFile), | |
1410 | format(string(Img), '<img src="~w">', GifFile), | |
1394 | 1411 | make_output_directory, |
1395 | 1412 | html_output_dir(Dir), |
1396 | 1413 | atomic_list_concat([Dir, '/', GifFile], OutFile), |
1471 | 1488 | |
1472 | 1489 | cmd('HTML'({Tag}), #code(Tag)). |
1473 | 1490 | cmd(latexcmd({Cmd}), #code(BslCmd)) :- |
1474 | concat(\, Cmd, BslCmd). | |
1491 | atom_concat(\, Cmd, BslCmd). | |
1475 | 1492 | cmd(latexenv({Env}), #code(Env)). |
1476 | 1493 | cmd(mode({Mode}), #code(Mode)). |
1477 | 1494 |
66 | 66 | ResY is Res0 * ScaleY, |
67 | 67 | ( ResX =:= ResY |
68 | 68 | -> Res = ResX |
69 | ; sformat(Res, '~wx~w', [ResX, ResY]) | |
69 | ; format(string(Res), '~wx~w', [ResX, ResY]) | |
70 | 70 | ), |
71 | 71 | BBX is -X1, |
72 | 72 | BBY is -Y1, |
119 | 119 | get_option(Options, device(Dev)), |
120 | 120 | get_option(Options, tmp(Tmp)), |
121 | 121 | ( get_option(Options, size(W, H)) |
122 | -> sformat(SCmd, '-g~wx~w', [W, H]) | |
122 | -> format(string(SCmd), '-g~wx~w', [W, H]) | |
123 | 123 | ; SCmd = '' |
124 | 124 | ), |
125 | 125 | aformat(Cmd, |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1997-2014, University of Amsterdam | |
5 | Copyright (c) 1997-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
33 | 33 | */ |
34 | 34 | |
35 | 35 | :- module(latex2html4pl, []). |
36 | :- use_module(latex2html). | |
36 | :- use_module(latex2html, | |
37 | [ latex2html_module/0, | |
38 | tex_load_commands/1, | |
39 | translate_table/3, | |
40 | clean_tt/2, | |
41 | add_to_index/2, | |
42 | add_to_index/1, | |
43 | translate_section/5, | |
44 | translate_section/4, | |
45 | op(_,_,_) | |
46 | ]). | |
47 | :- autoload(library(apply),[maplist/3,maplist/2]). | |
48 | :- autoload(library(lists),[append/3,delete/3]). | |
49 | :- autoload(library(occurs),[sub_term/2]). | |
50 | :- autoload(library(readutil),[read_line_to_codes/2]). | |
37 | 51 | |
38 | 52 | :- latex2html_module. |
39 | 53 | :- tex_load_commands(pl). |
83 | 97 | cmd(hrule, html('<hr>')). |
84 | 98 | cmd(bug({TeX}), #footnote(bug, +TeX)). |
85 | 99 | cmd(fileext({Ext}), #code(Text)) :- |
86 | sformat(Text, '.~w', [Ext]). | |
100 | format(string(Text), '.~w', [Ext]). | |
87 | 101 | |
88 | 102 | cmd(var( {A1}), #var(+A1)). |
89 | 103 | cmd(arg( {A1}), #var(+A1)). |
116 | 130 | nospace(=)]), #var(+A2)]). |
117 | 131 | cmd(fmtseq( {A1}), #code(A1)). |
118 | 132 | cmd(versionshort, _, nospace(Version)) :- |
119 | feature(version, V), | |
133 | current_prolog_flag(version, V), | |
120 | 134 | Major is V // 10000, |
121 | 135 | Minor is (V // 100) mod 100, |
122 | 136 | Patch is V mod 100, |
130 | 144 | cmd(predref({RawName}, {Arity}), #lref(pred, RefName, Text)) :- |
131 | 145 | clean_name(RawName, Name), |
132 | 146 | predicate_refname(Name, Arity, RefName), |
133 | sformat(Text, '~w/~w', [Name, Arity]). | |
147 | format(string(Text), '~w/~w', [Name, Arity]). | |
134 | 148 | cmd(funcref({RawName}, {Arity}), #lref(function, RefName, Text)) :- |
135 | 149 | clean_name(RawName, Name), |
136 | 150 | function_refname(Name, Arity, RefName), |
137 | sformat(Text, '~w/~w', [Name, Arity]). | |
151 | format(string(Text), '~w/~w', [Name, Arity]). | |
138 | 152 | cmd(dcgref({RawName}, {DCGArity}), #lref(pred, RefName, Text)) :- |
139 | 153 | clean_name(RawName, Name), |
140 | 154 | atom_number(DCGArity, Arity), |
141 | 155 | dcg_refname(Name, Arity, RefName), |
142 | sformat(Text, '~w//~w', [Name, Arity]). | |
156 | format(string(Text), '~w//~w', [Name, Arity]). | |
143 | 157 | cmd(qpredref({Module}, {RawName}, {Arity}), #lref(pred, RefName, Text)) :- |
144 | 158 | clean_name(RawName, Name), |
145 | 159 | predicate_refname(Module:Name, Arity, RefName), |
419 | 433 | |
420 | 434 | cmd(classitem({Class}), |
421 | 435 | #defitem(#label(RefName, #strong(Class)))) :- |
422 | sformat(RefName, 'class:~w', [Class]). | |
436 | format(string(RefName), 'class:~w', [Class]). | |
423 | 437 | cmd(constructor({Class}, {Args}), |
424 | 438 | #defitem([#strong([Class, ::, Class]), #embrace(#var(+Args))])). |
425 | 439 | cmd(destructor({Class}), |
431 | 445 | % Some XPCE things |
432 | 446 | |
433 | 447 | cmd(class({Name}), #lref(Label, Name)) :- |
434 | concat('class:', Name, Label), | |
448 | atom_concat('class:', Name, Label), | |
435 | 449 | add_to_index(Name). |
436 | 450 | cmd(noclass({Name}), #i(Name)). |
437 | 451 | cmd(menuref({A1}), #lref(RefName, Name)) :- |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1999-2013, University of Amsterdam | |
5 | Copyright (c) 1999-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
33 | 33 | */ |
34 | 34 | |
35 | 35 | :- module(latex2html4xpce, []). |
36 | :- use_module(library(latex2html/latex2html)). | |
36 | :- autoload(library(apply),[maplist/3]). | |
37 | :- autoload(library(lists),[append/3]). | |
38 | :- autoload(library(latex2html/latex2html), | |
39 | [ latex2html_module/0, | |
40 | tex_load_commands/1, | |
41 | translate/3, | |
42 | add_to_index/1, | |
43 | clean_tt/2, | |
44 | add_to_index/2, | |
45 | translate_table/3 | |
46 | ]). | |
37 | 47 | |
38 | 48 | :- latex2html_module. |
39 | 49 | :- tex_load_commands(xpce). |
72 | 82 | cmd(objectname({Name}), #b([nospace(@), Name])). |
73 | 83 | cmd(noclass({Name}), #b(Name)). |
74 | 84 | cmd(class({Name}), #lref(Label, Name)) :- |
75 | concat('class:', Name, Label), | |
85 | atom_concat('class:', Name, Label), | |
76 | 86 | add_to_index(Name). |
77 | 87 | cmd(classs({Name}), #lref(Label, NameS)) :- |
78 | concat('class:', Name, Label), | |
79 | concat(Name, s, NameS), | |
88 | atom_concat('class:', Name, Label), | |
89 | atom_concat(Name, s, NameS), | |
80 | 90 | add_to_index(Name). |
81 | 91 | cmd(tool({Name}), #strong(+Name)). |
82 | 92 | cmd(demo({Name}), #strong(+Name)). |
103 | 113 | #defitem([ #strong(+Descr), ' ', #i(#embrace(+Menu))])). |
104 | 114 | cmd(secoverview({Label}, {Title}), |
105 | 115 | [ html('<li>'), #lref(RefName, +Title) ]) :- |
106 | sformat(RefName, 'sec:~w', Label). | |
116 | format(string(RefName), 'sec:~w', Label). | |
107 | 117 | cmd(classsummary(_M, {RawClass}, {Args}, {_FigRef}), |
108 | 118 | #defitem(#label(Label, [#strong(Class), #embrace(#var(+Args))]))) :- |
109 | 119 | clean_tt(RawClass, Class), |
110 | concat('class:', Class, Label), | |
120 | atom_concat('class:', Class, Label), | |
111 | 121 | add_to_index(Class, +Label). |
112 | 122 | cmd(fontalias({Alias}, {Term}), #defitem([#code(Alias), #i(+Term)])). |
113 | 123 | cmd(noargpredicate(Name), HTML) :- |
116 | 126 | % add_to_index(Term). |
117 | 127 | cmd(glossitem({Term}), #defitem(#label(RefName, #strong(Term)))) :- |
118 | 128 | canonicalise_glossitem(Term, Ref), |
119 | sformat(RefName, 'gloss:~w', [Ref]). | |
129 | format(string(RefName), 'gloss:~w', [Ref]). | |
120 | 130 | cmd(g({Term}), #lref(RefName, Term)) :- |
121 | 131 | canonicalise_glossitem(Term, Ref), |
122 | sformat(RefName, 'gloss:~w', [Ref]). | |
132 | format(string(RefName), 'gloss:~w', [Ref]). | |
123 | 133 | cmd(line({Tokens}), #quote(Line)) :- |
124 | 134 | translate(Tokens, normal, Line). |
125 | 135 | cmd(classvar({Class}, {Var}), #b([#code([+Class,nospace('.'),+Var])])). |
0 | #!/bin/sh | |
1 | # | |
2 | # install - install a program, script, or datafile | |
3 | # This comes from X11R5. | |
4 | # | |
5 | # Calling this script install-sh is preferred over install.sh, to prevent | |
6 | # `make' implicit rules from creating a file called install from it | |
7 | # when there is no Makefile. | |
8 | # | |
9 | # This script is compatible with the BSD install script, but was written | |
10 | # from scratch. | |
11 | # | |
12 | ||
13 | ||
14 | # set DOITPROG to echo to test this script | |
15 | ||
16 | # Don't use :- since 4.3BSD and earlier shells don't like it. | |
17 | doit="${DOITPROG-}" | |
18 | ||
19 | ||
20 | # put in absolute paths if you don't have them in your path; or use env. vars. | |
21 | ||
22 | mvprog="${MVPROG-mv}" | |
23 | cpprog="${CPPROG-cp}" | |
24 | chmodprog="${CHMODPROG-chmod}" | |
25 | chownprog="${CHOWNPROG-chown}" | |
26 | chgrpprog="${CHGRPPROG-chgrp}" | |
27 | stripprog="${STRIPPROG-strip}" | |
28 | rmprog="${RMPROG-rm}" | |
29 | mkdirprog="${MKDIRPROG-mkdir}" | |
30 | ||
31 | tranformbasename="" | |
32 | transform_arg="" | |
33 | instcmd="$mvprog" | |
34 | chmodcmd="$chmodprog 0755" | |
35 | chowncmd="" | |
36 | chgrpcmd="" | |
37 | stripcmd="" | |
38 | rmcmd="$rmprog -f" | |
39 | mvcmd="$mvprog" | |
40 | src="" | |
41 | dst="" | |
42 | dir_arg="" | |
43 | ||
44 | while [ x"$1" != x ]; do | |
45 | case $1 in | |
46 | -c) instcmd="$cpprog" | |
47 | shift | |
48 | continue;; | |
49 | ||
50 | -d) dir_arg=true | |
51 | shift | |
52 | continue;; | |
53 | ||
54 | -m) chmodcmd="$chmodprog $2" | |
55 | shift | |
56 | shift | |
57 | continue;; | |
58 | ||
59 | -o) chowncmd="$chownprog $2" | |
60 | shift | |
61 | shift | |
62 | continue;; | |
63 | ||
64 | -g) chgrpcmd="$chgrpprog $2" | |
65 | shift | |
66 | shift | |
67 | continue;; | |
68 | ||
69 | -s) stripcmd="$stripprog" | |
70 | shift | |
71 | continue;; | |
72 | ||
73 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` | |
74 | shift | |
75 | continue;; | |
76 | ||
77 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` | |
78 | shift | |
79 | continue;; | |
80 | ||
81 | *) if [ x"$src" = x ] | |
82 | then | |
83 | src=$1 | |
84 | else | |
85 | # this colon is to work around a 386BSD /bin/sh bug | |
86 | : | |
87 | dst=$1 | |
88 | fi | |
89 | shift | |
90 | continue;; | |
91 | esac | |
92 | done | |
93 | ||
94 | if [ x"$src" = x ] | |
95 | then | |
96 | echo "install: no input file specified" | |
97 | exit 1 | |
98 | else | |
99 | true | |
100 | fi | |
101 | ||
102 | if [ x"$dir_arg" != x ]; then | |
103 | dst=$src | |
104 | src="" | |
105 | ||
106 | if [ -d $dst ]; then | |
107 | instcmd=: | |
108 | else | |
109 | instcmd=mkdir | |
110 | fi | |
111 | else | |
112 | ||
113 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command | |
114 | # might cause directories to be created, which would be especially bad | |
115 | # if $src (and thus $dsttmp) contains '*'. | |
116 | ||
117 | if [ -f $src -o -d $src ] | |
118 | then | |
119 | true | |
120 | else | |
121 | echo "install: $src does not exist" | |
122 | exit 1 | |
123 | fi | |
124 | ||
125 | if [ x"$dst" = x ] | |
126 | then | |
127 | echo "install: no destination specified" | |
128 | exit 1 | |
129 | else | |
130 | true | |
131 | fi | |
132 | ||
133 | # If destination is a directory, append the input filename; if your system | |
134 | # does not like double slashes in filenames, you may need to add some logic | |
135 | ||
136 | if [ -d $dst ] | |
137 | then | |
138 | dst="$dst"/`basename $src` | |
139 | else | |
140 | true | |
141 | fi | |
142 | fi | |
143 | ||
144 | ## this sed command emulates the dirname command | |
145 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | |
146 | ||
147 | # Make sure that the destination directory exists. | |
148 | # this part is taken from Noah Friedman's mkinstalldirs script | |
149 | ||
150 | # Skip lots of stat calls in the usual case. | |
151 | if [ ! -d "$dstdir" ]; then | |
152 | defaultIFS=' | |
153 | ' | |
154 | IFS="${IFS-${defaultIFS}}" | |
155 | ||
156 | oIFS="${IFS}" | |
157 | # Some sh's can't handle IFS=/ for some reason. | |
158 | IFS='%' | |
159 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` | |
160 | IFS="${oIFS}" | |
161 | ||
162 | pathcomp='' | |
163 | ||
164 | while [ $# -ne 0 ] ; do | |
165 | pathcomp="${pathcomp}${1}" | |
166 | shift | |
167 | ||
168 | if [ ! -d "${pathcomp}" ] ; | |
169 | then | |
170 | $mkdirprog "${pathcomp}" | |
171 | else | |
172 | true | |
173 | fi | |
174 | ||
175 | pathcomp="${pathcomp}/" | |
176 | done | |
177 | fi | |
178 | ||
179 | if [ x"$dir_arg" != x ] | |
180 | then | |
181 | $doit $instcmd $dst && | |
182 | ||
183 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && | |
184 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && | |
185 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && | |
186 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi | |
187 | else | |
188 | ||
189 | # If we're going to rename the final executable, determine the name now. | |
190 | ||
191 | if [ x"$transformarg" = x ] | |
192 | then | |
193 | dstfile=`basename $dst` | |
194 | else | |
195 | dstfile=`basename $dst $transformbasename | | |
196 | sed $transformarg`$transformbasename | |
197 | fi | |
198 | ||
199 | # don't allow the sed command to completely eliminate the filename | |
200 | ||
201 | if [ x"$dstfile" = x ] | |
202 | then | |
203 | dstfile=`basename $dst` | |
204 | else | |
205 | true | |
206 | fi | |
207 | ||
208 | # Make a temp file name in the proper directory. | |
209 | ||
210 | dsttmp=$dstdir/#inst.$$# | |
211 | ||
212 | # Move or copy the file name to the temp name | |
213 | ||
214 | $doit $instcmd $src $dsttmp && | |
215 | ||
216 | trap "rm -f ${dsttmp}" 0 && | |
217 | ||
218 | # and set any options; do chmod last to preserve setuid bits | |
219 | ||
220 | # If any of these fail, we abort the whole thing. If we want to | |
221 | # ignore errors from any of these, just make sure not to ignore | |
222 | # errors from the above "$doit $instcmd $src $dsttmp" command. | |
223 | ||
224 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && | |
225 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && | |
226 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && | |
227 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && | |
228 | ||
229 | # Now rename the file to the real destination. | |
230 | ||
231 | $doit $rmcmd -f $dstdir/$dstfile && | |
232 | $doit $mvcmd $dsttmp $dstdir/$dstfile | |
233 | ||
234 | fi && | |
235 | ||
236 | ||
237 | exit 0 |
50 | 50 | % Hook support |
51 | 51 | paxos_replicate_key/3 % +Nodes, ?Key, +Options |
52 | 52 | ]). |
53 | :- use_module(library(broadcast)). | |
54 | :- use_module(library(debug)). | |
55 | :- use_module(library(lists)). | |
56 | :- use_module(library(settings)). | |
57 | :- use_module(library(option)). | |
58 | :- use_module(library(error)). | |
59 | :- use_module(library(apply)). | |
60 | :- use_module(library(solution_sequences)). | |
53 | :- autoload(library(apply),[partition/4,maplist/3]). | |
54 | :- autoload(library(broadcast), | |
55 | [ listen/3, | |
56 | broadcast_request/1, | |
57 | broadcast/1, | |
58 | unlisten/1, | |
59 | listen/2, | |
60 | unlisten/2 | |
61 | ]). | |
62 | :- autoload(library(debug),[debug/3]). | |
63 | :- autoload(library(error), | |
64 | [permission_error/3,resource_error/1,must_be/2]). | |
65 | :- autoload(library(lists),[select/3,nth1/3,max_list/2,member/2]). | |
66 | :- autoload(library(option),[option/2,option/3]). | |
67 | :- autoload(library(solution_sequences),[call_nth/2]). | |
68 | :- use_module(library(settings),[setting/4,setting/2]). | |
61 | 69 | |
62 | 70 | /** <module> A Replicated Data Store |
63 | 71 |
172 | 172 | % day:20, month:4, year:2017}. |
173 | 173 | % |
174 | 174 | % ``` |
175 | % | |
176 | % @arg Options Only _execution_ options are processed. See re_match/3 | |
177 | % for the set of options. _Compilation_ options must be passed as | |
178 | % `/flags` to Regex. | |
179 | % @arg Regex See re_match/2 for a description of this argument. | |
175 | 180 | |
176 | 181 | re_matchsub(Regex, String, Subs, Options) :- |
177 | 182 | re_compiled(Regex, Compiled), |
0 | #!/bin/sh | |
1 | # | |
2 | # install - install a program, script, or datafile | |
3 | # This comes from X11R5. | |
4 | # | |
5 | # Calling this script install-sh is preferred over install.sh, to prevent | |
6 | # `make' implicit rules from creating a file called install from it | |
7 | # when there is no Makefile. | |
8 | # | |
9 | # This script is compatible with the BSD install script, but was written | |
10 | # from scratch. | |
11 | # | |
12 | ||
13 | ||
14 | # set DOITPROG to echo to test this script | |
15 | ||
16 | # Don't use :- since 4.3BSD and earlier shells don't like it. | |
17 | doit="${DOITPROG-}" | |
18 | ||
19 | ||
20 | # put in absolute paths if you don't have them in your path; or use env. vars. | |
21 | ||
22 | mvprog="${MVPROG-mv}" | |
23 | cpprog="${CPPROG-cp}" | |
24 | chmodprog="${CHMODPROG-chmod}" | |
25 | chownprog="${CHOWNPROG-chown}" | |
26 | chgrpprog="${CHGRPPROG-chgrp}" | |
27 | stripprog="${STRIPPROG-strip}" | |
28 | rmprog="${RMPROG-rm}" | |
29 | mkdirprog="${MKDIRPROG-mkdir}" | |
30 | ||
31 | tranformbasename="" | |
32 | transform_arg="" | |
33 | instcmd="$mvprog" | |
34 | chmodcmd="$chmodprog 0755" | |
35 | chowncmd="" | |
36 | chgrpcmd="" | |
37 | stripcmd="" | |
38 | rmcmd="$rmprog -f" | |
39 | mvcmd="$mvprog" | |
40 | src="" | |
41 | dst="" | |
42 | dir_arg="" | |
43 | ||
44 | while [ x"$1" != x ]; do | |
45 | case $1 in | |
46 | -c) instcmd="$cpprog" | |
47 | shift | |
48 | continue;; | |
49 | ||
50 | -d) dir_arg=true | |
51 | shift | |
52 | continue;; | |
53 | ||
54 | -m) chmodcmd="$chmodprog $2" | |
55 | shift | |
56 | shift | |
57 | continue;; | |
58 | ||
59 | -o) chowncmd="$chownprog $2" | |
60 | shift | |
61 | shift | |
62 | continue;; | |
63 | ||
64 | -g) chgrpcmd="$chgrpprog $2" | |
65 | shift | |
66 | shift | |
67 | continue;; | |
68 | ||
69 | -s) stripcmd="$stripprog" | |
70 | shift | |
71 | continue;; | |
72 | ||
73 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` | |
74 | shift | |
75 | continue;; | |
76 | ||
77 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` | |
78 | shift | |
79 | continue;; | |
80 | ||
81 | *) if [ x"$src" = x ] | |
82 | then | |
83 | src=$1 | |
84 | else | |
85 | # this colon is to work around a 386BSD /bin/sh bug | |
86 | : | |
87 | dst=$1 | |
88 | fi | |
89 | shift | |
90 | continue;; | |
91 | esac | |
92 | done | |
93 | ||
94 | if [ x"$src" = x ] | |
95 | then | |
96 | echo "install: no input file specified" | |
97 | exit 1 | |
98 | else | |
99 | true | |
100 | fi | |
101 | ||
102 | if [ x"$dir_arg" != x ]; then | |
103 | dst=$src | |
104 | src="" | |
105 | ||
106 | if [ -d $dst ]; then | |
107 | instcmd=: | |
108 | else | |
109 | instcmd=mkdir | |
110 | fi | |
111 | else | |
112 | ||
113 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command | |
114 | # might cause directories to be created, which would be especially bad | |
115 | # if $src (and thus $dsttmp) contains '*'. | |
116 | ||
117 | if [ -f $src -o -d $src ] | |
118 | then | |
119 | true | |
120 | else | |
121 | echo "install: $src does not exist" | |
122 | exit 1 | |
123 | fi | |
124 | ||
125 | if [ x"$dst" = x ] | |
126 | then | |
127 | echo "install: no destination specified" | |
128 | exit 1 | |
129 | else | |
130 | true | |
131 | fi | |
132 | ||
133 | # If destination is a directory, append the input filename; if your system | |
134 | # does not like double slashes in filenames, you may need to add some logic | |
135 | ||
136 | if [ -d $dst ] | |
137 | then | |
138 | dst="$dst"/`basename $src` | |
139 | else | |
140 | true | |
141 | fi | |
142 | fi | |
143 | ||
144 | ## this sed command emulates the dirname command | |
145 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | |
146 | ||
147 | # Make sure that the destination directory exists. | |
148 | # this part is taken from Noah Friedman's mkinstalldirs script | |
149 | ||
150 | # Skip lots of stat calls in the usual case. | |
151 | if [ ! -d "$dstdir" ]; then | |
152 | defaultIFS=' | |
153 | ' | |
154 | IFS="${IFS-${defaultIFS}}" | |
155 | ||
156 | oIFS="${IFS}" | |
157 | # Some sh's can't handle IFS=/ for some reason. | |
158 | IFS='%' | |
159 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` | |
160 | IFS="${oIFS}" | |
161 | ||
162 | pathcomp='' | |
163 | ||
164 | while [ $# -ne 0 ] ; do | |
165 | pathcomp="${pathcomp}${1}" | |
166 | shift | |
167 | ||
168 | if [ ! -d "${pathcomp}" ] ; | |
169 | then | |
170 | $mkdirprog "${pathcomp}" | |
171 | else | |
172 | true | |
173 | fi | |
174 | ||
175 | pathcomp="${pathcomp}/" | |
176 | done | |
177 | fi | |
178 | ||
179 | if [ x"$dir_arg" != x ] | |
180 | then | |
181 | $doit $instcmd $dst && | |
182 | ||
183 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && | |
184 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && | |
185 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && | |
186 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi | |
187 | else | |
188 | ||
189 | # If we're going to rename the final executable, determine the name now. | |
190 | ||
191 | if [ x"$transformarg" = x ] | |
192 | then | |
193 | dstfile=`basename $dst` | |
194 | else | |
195 | dstfile=`basename $dst $transformbasename | | |
196 | sed $transformarg`$transformbasename | |
197 | fi | |
198 | ||
199 | # don't allow the sed command to completely eliminate the filename | |
200 | ||
201 | if [ x"$dstfile" = x ] | |
202 | then | |
203 | dstfile=`basename $dst` | |
204 | else | |
205 | true | |
206 | fi | |
207 | ||
208 | # Make a temp file name in the proper directory. | |
209 | ||
210 | dsttmp=$dstdir/#inst.$$# | |
211 | ||
212 | # Move or copy the file name to the temp name | |
213 | ||
214 | $doit $instcmd $src $dsttmp && | |
215 | ||
216 | trap "rm -f ${dsttmp}" 0 && | |
217 | ||
218 | # and set any options; do chmod last to preserve setuid bits | |
219 | ||
220 | # If any of these fail, we abort the whole thing. If we want to | |
221 | # ignore errors from any of these, just make sure not to ignore | |
222 | # errors from the above "$doit $instcmd $src $dsttmp" command. | |
223 | ||
224 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && | |
225 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && | |
226 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && | |
227 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && | |
228 | ||
229 | # Now rename the file to the real destination. | |
230 | ||
231 | $doit $rmcmd -f $dstdir/$dstfile && | |
232 | $doit $mvcmd $dsttmp $dstdir/$dstfile | |
233 | ||
234 | fi && | |
235 | ||
236 | ||
237 | exit 0 |
66 | 66 | @author Torbjörn Lager and Jan Wielemaker |
67 | 67 | */ |
68 | 68 | |
69 | :- use_module(library(http/http_dispatch)). | |
70 | :- use_module(library(http/http_parameters)). | |
71 | :- use_module(library(http/http_client)). | |
72 | :- use_module(library(http/http_json)). | |
73 | :- use_module(library(http/http_open)). | |
74 | :- use_module(library(http/http_stream)). | |
75 | :- use_module(library(http/http_wrapper)). | |
76 | :- use_module(library(http/http_cors)). | |
77 | :- use_module(library(thread_pool)). | |
78 | :- use_module(library(broadcast)). | |
79 | :- use_module(library(uri)). | |
80 | :- use_module(library(filesex)). | |
81 | :- use_module(library(time)). | |
82 | :- use_module(library(lists)). | |
83 | :- use_module(library(charsio)). | |
84 | :- use_module(library(apply)). | |
85 | :- use_module(library(aggregate)). | |
86 | :- use_module(library(option)). | |
87 | :- use_module(library(settings)). | |
88 | :- use_module(library(debug)). | |
89 | :- use_module(library(error)). | |
90 | :- use_module(library(sandbox)). | |
91 | :- use_module(library(modules)). | |
92 | :- use_module(library(term_to_json)). | |
69 | :- autoload(library(aggregate),[aggregate_all/3]). | |
70 | :- autoload(library(apply),[maplist/2,partition/4,exclude/3,maplist/3]). | |
71 | :- autoload(library(broadcast),[broadcast/1]). | |
72 | :- autoload(library(charsio),[open_chars_stream/2]). | |
73 | :- autoload(library(debug),[debug/1,debugging/1,debug/3,assertion/1]). | |
74 | :- autoload(library(error), | |
75 | [ must_be/2, | |
76 | existence_error/2, | |
77 | permission_error/3, | |
78 | domain_error/2 | |
79 | ]). | |
80 | :- autoload(library(filesex),[directory_file_path/3]). | |
81 | :- autoload(library(listing),[listing/1]). | |
82 | :- autoload(library(lists),[member/2,flatten/2,select/3,append/3]). | |
83 | :- autoload(library(modules),[in_temporary_module/3]). | |
84 | :- autoload(library(occurs),[sub_term/2]). | |
85 | :- autoload(library(option), | |
86 | [select_option/3,option/2,option/3,select_option/4]). | |
87 | :- autoload(library(prolog_stack),[print_prolog_backtrace/2]). | |
88 | :- autoload(library(sandbox),[safe_goal/1]). | |
89 | :- autoload(library(statistics),[thread_statistics/2]). | |
90 | :- autoload(library(term_to_json),[term_to_json/2]). | |
91 | :- autoload(library(thread_pool), | |
92 | [thread_pool_create/3,thread_create_in_pool/4]). | |
93 | :- autoload(library(time),[alarm/4,call_with_time_limit/2]). | |
94 | :- autoload(library(uri), | |
95 | [ uri_components/2, | |
96 | uri_query_components/2, | |
97 | uri_data/3, | |
98 | uri_data/4, | |
99 | uri_encoded/3 | |
100 | ]). | |
101 | :- autoload(library(http/http_client),[http_read_data/3]). | |
102 | :- autoload(library(http/http_cors),[cors_enable/0,cors_enable/2]). | |
103 | :- autoload(library(http/http_dispatch), | |
104 | [http_handler/3,http_404/2,http_reply_file/3]). | |
105 | :- autoload(library(http/http_open),[http_open/3]). | |
106 | :- autoload(library(http/http_parameters),[http_parameters/2]). | |
107 | :- autoload(library(http/http_stream),[is_cgi_stream/1]). | |
108 | :- autoload(library(http/http_wrapper),[http_peer/2]). | |
109 | ||
110 | :- use_module(library(settings),[setting/2,setting/4]). | |
111 | :- use_module(library(http/http_json), | |
112 | [http_read_json_dict/2,reply_json/1]). | |
113 | ||
93 | 114 | :- if(exists_source(library(uuid))). |
94 | :- use_module(library(uuid)). | |
115 | :- autoload(library(uuid), [uuid/2]). | |
95 | 116 | :- endif. |
96 | 117 | |
97 | 118 | |
688 | 709 | pengine_uuid(Id) :- |
689 | 710 | uuid(Id, [version(4)]). % Version 4 is random. |
690 | 711 | :- else. |
691 | :- use_module(library(random)). | |
692 | 712 | pengine_uuid(Id) :- |
693 | 713 | ( current_prolog_flag(max_integer, Max1) |
694 | 714 | -> Max is Max1-1 |
973 | 993 | % |
974 | 994 | % On demand creation of a thread pool for a pengine application. |
975 | 995 | |
996 | :- multifile thread_pool:create_pool/1. | |
997 | ||
976 | 998 | thread_pool:create_pool(Application) :- |
977 | 999 | current_application(Application), |
978 | 1000 | setting(Application:thread_pool_size, Size), |
60 | 60 | |
61 | 61 | message_lines_to_html/3 % +Lines, +Classes, -HTML |
62 | 62 | ]). |
63 | :- use_module(library(lists)). | |
64 | :- use_module(library(pengines)). | |
65 | :- use_module(library(option)). | |
66 | :- use_module(library(debug)). | |
67 | :- use_module(library(error)). | |
68 | :- use_module(library(apply)). | |
69 | :- use_module(library(settings)). | |
70 | :- use_module(library(listing)). | |
71 | :- use_module(library(yall)). | |
63 | :- autoload(library(apply),[foldl/4,maplist/3,maplist/4]). | |
64 | :- autoload(library(backcomp),[thread_at_exit/1]). | |
65 | :- autoload(library(debug),[assertion/1]). | |
66 | :- autoload(library(error),[must_be/2]). | |
67 | :- autoload(library(listing),[listing/1,portray_clause/1]). | |
68 | :- autoload(library(lists),[append/2,append/3,subtract/3]). | |
69 | :- autoload(library(option),[option/3,merge_options/3]). | |
70 | :- autoload(library(pengines), | |
71 | [ pengine_self/1, | |
72 | pengine_output/1, | |
73 | pengine_input/2, | |
74 | pengine_property/2 | |
75 | ]). | |
76 | :- autoload(library(prolog_stream),[open_prolog_stream/4]). | |
77 | :- autoload(library(readutil),[read_line_to_string/2]). | |
78 | :- autoload(library(yall),[(>>)/4]). | |
79 | :- autoload(library(http/html_write),[html/3,print_html/1]). | |
80 | :- autoload(library(http/term_html),[term/4]). | |
81 | :- use_module(library(settings),[setting/4,setting/2]). | |
82 | ||
72 | 83 | :- use_module(library(sandbox), []). |
73 | :- use_module(library(http/html_write)). | |
74 | :- use_module(library(http/term_html)). | |
75 | 84 | :- if(exists_source(library(prolog_stream))). |
76 | :- use_module(library(prolog_stream)). | |
77 | 85 | :- endif. |
78 | 86 | |
79 | 87 | :- html_meta send_html(html). |
33 | 33 | |
34 | 34 | :- module(pengines_sandbox, []). |
35 | 35 | :- use_module(library(pengines), []). |
36 | :- use_module(library(lists)). | |
37 | :- use_module(library(error)). | |
36 | :- autoload(library(error),[instantiation_error/1]). | |
37 | :- autoload(library(lists),[append/3]). | |
38 | 38 | |
39 | 39 | /** <module> Declare Pengine interaction sandbox-safe |
40 | 40 |
37 | 37 | [ term_to_json/3, % +Term, +Bindings, -Json |
38 | 38 | term_to_json/2 % +Term, -Json |
39 | 39 | ]). |
40 | :- use_module(library(apply)). | |
41 | :- use_module(library(error)). | |
40 | :- autoload(library(apply),[maplist/2,maplist/3]). | |
41 | :- autoload(library(error),[must_be/2,domain_error/2]). | |
42 | 42 | |
43 | 43 | %! term_to_json(+Term, +Bindings, -JsonTerm) is det. |
44 | 44 | %! term_to_json(+Term, -JsonTerm) is det. |
0 | % setup paths to load relevant packages from development environment | |
1 | :- asserta(user:file_search_path(foreign, '../http')). | |
2 | :- asserta(user:file_search_path(foreign, '../clib')). | |
3 | :- asserta(user:file_search_path(foreign, '../sgml')). | |
4 | :- asserta(user:file_search_path(library, '.')). | |
5 | :- asserta(user:file_search_path(library, '..')). | |
6 | :- asserta(user:file_search_path(library, '../sgml')). | |
7 | :- asserta(user:file_search_path(library, '../plunit')). | |
8 | :- asserta(user:file_search_path(library, '../clib')). | |
9 | :- asserta(user:file_search_path(dtd, '../sgml/DTD')). | |
10 | ||
11 | % Hack: auto-loading this does not work. | |
12 | :- [library(charsio)]. | |
13 | :- [charsio:library(memfile)]. |
35 | 35 | [ test_pengines/0, |
36 | 36 | pengine_server/0 % start server |
37 | 37 | ]). |
38 | :- include(test_local). | |
39 | 38 | |
40 | 39 | :- debug(pengine(delay)). |
41 | 40 | % run pengine server for remote tests in a separate process. |
35 | 35 | [ test_term_html/0, |
36 | 36 | term_html_string/3 % @Term, -String, +Options |
37 | 37 | ]). |
38 | :- include(test_local). | |
39 | 38 | |
40 | 39 | :- use_module(library(plunit)). |
41 | 40 | :- use_module(library(debug)). |
82 | 82 | synonym(char, character, 0.8). |
83 | 83 | synonym(clone, duplicate, 0.3). |
84 | 84 | synonym(close, destroy, 0.3). |
85 | synonym(comma, conjunction, 0.3). | |
85 | 86 | synonym(concat, concatenate, 0.8). |
86 | 87 | synonym(console, terminal, 0.7). |
87 | 88 | synonym(consult, compile, 0.7). |
144 | 145 | synonym(run, call, 0.3). |
145 | 146 | synonym(same, equivalent, 0.8). |
146 | 147 | synonym(screen, console, 0.5). |
148 | synonym(semincolon,disjunction, 0.3). | |
147 | 149 | synonym(sin, sine, 0.9). |
148 | 150 | synonym(size, memory, 0.3). |
149 | 151 | synonym(smaller, less, 0.5). |
53 | 53 | @license GPL+SWI-exception or Artistic 2.0 |
54 | 54 | */ |
55 | 55 | |
56 | :- use_module(library(apply)). | |
57 | :- use_module(library(ordsets), [ord_intersection/3]). | |
56 | :- autoload(library(apply),[maplist/3,include/3]). | |
57 | :- autoload(library(lists),[member/2,append/2]). | |
58 | :- autoload(library(option),[option/3,option/2]). | |
59 | :- autoload(library(ordsets),[ord_intersection/3]). | |
60 | :- autoload(library(pairs),[group_pairs_by_key/2,pairs_values/2]). | |
61 | ||
58 | 62 | :- meta_predicate valid_options(+, 1). |
59 | 63 | |
60 | 64 | |
114 | 118 | throw(error(Error_term,context(Impldef,_))). |
115 | 119 | |
116 | 120 | :- set_prolog_flag(generate_debug_info, false). |
117 | :- use_module(library(option)). | |
118 | :- use_module(library(pairs)). | |
119 | ||
120 | 121 | current_test_flag(Name, Value) :- |
121 | 122 | current_prolog_flag(Name, Value). |
122 | 123 | |
140 | 141 | throw_error(Error_term,Impldef) :- |
141 | 142 | throw(error(Error_term,i(Impldef))). % SICStus 3 work around |
142 | 143 | |
143 | :- use_module(swi). % SWI-Compatibility | |
144 | :- use_module(library(terms)). | |
144 | % SWI-Compatibility | |
145 | 145 | :- op(700, xfx, =@=). |
146 | 146 | |
147 | 147 | '$set_source_module'(_, _). |
183 | 183 | /******************************* |
184 | 184 | * IMPORTS * |
185 | 185 | *******************************/ |
186 | ||
187 | :- use_module(library(lists)). | |
188 | 186 | |
189 | 187 | :- initialization |
190 | 188 | ( current_test_flag(test_options, _) |
474 | 472 | *******************************/ |
475 | 473 | |
476 | 474 | :- if(swi). |
477 | :- use_module(library(error)). | |
478 | 475 | :- else. |
479 | 476 | must_be(list, X) :- |
480 | 477 | !, |
36 | 36 | [ show_coverage/1, % :Goal |
37 | 37 | show_coverage/2 |
38 | 38 | ]). |
39 | :- use_module(library(ordsets)). | |
40 | :- use_module(library(apply)). | |
39 | :- autoload(library(apply),[exclude/3,maplist/3,include/3,maplist/2]). | |
40 | :- autoload(library(edinburgh),[nodebug/0]). | |
41 | :- autoload(library(ordsets), | |
42 | [ord_intersect/2,ord_intersection/3,ord_subtract/3]). | |
43 | :- autoload(library(pairs),[group_pairs_by_key/2]). | |
41 | 44 | |
42 | 45 | :- set_prolog_flag(generate_debug_info, false). |
43 | 46 |
36 | 36 | [ make_tests/3, % +Module, +File, +Out |
37 | 37 | make_test/3 % +Callable, -Module, -Test |
38 | 38 | ]). |
39 | :- use_module(library(time)). | |
40 | :- use_module(library(lists)). | |
41 | :- use_module(library(listing)). | |
42 | :- use_module(library(readutil)). | |
39 | :- autoload(library(apply),[maplist/2]). | |
40 | :- autoload(library(listing),[portray_clause/2]). | |
41 | :- autoload(library(lists),[member/2]). | |
42 | :- autoload(library(readutil),[read_file_to_terms/3]). | |
43 | :- autoload(library(time),[call_with_time_limit/2]). | |
43 | 44 | |
44 | 45 | /** <module> Test Generation Wizard |
45 | 46 |
0 | #!/bin/sh | |
1 | # | |
2 | # install - install a program, script, or datafile | |
3 | # This comes from X11R5. | |
4 | # | |
5 | # Calling this script install-sh is preferred over install.sh, to prevent | |
6 | # `make' implicit rules from creating a file called install from it | |
7 | # when there is no Makefile. | |
8 | # | |
9 | # This script is compatible with the BSD install script, but was written | |
10 | # from scratch. | |
11 | # | |
12 | ||
13 | ||
14 | # set DOITPROG to echo to test this script | |
15 | ||
16 | # Don't use :- since 4.3BSD and earlier shells don't like it. | |
17 | doit="${DOITPROG-}" | |
18 | ||
19 | ||
20 | # put in absolute paths if you don't have them in your path; or use env. vars. | |
21 | ||
22 | mvprog="${MVPROG-mv}" | |
23 | cpprog="${CPPROG-cp}" | |
24 | chmodprog="${CHMODPROG-chmod}" | |
25 | chownprog="${CHOWNPROG-chown}" | |
26 | chgrpprog="${CHGRPPROG-chgrp}" | |
27 | stripprog="${STRIPPROG-strip}" | |
28 | rmprog="${RMPROG-rm}" | |
29 | mkdirprog="${MKDIRPROG-mkdir}" | |
30 | ||
31 | tranformbasename="" | |
32 | transform_arg="" | |
33 | instcmd="$mvprog" | |
34 | chmodcmd="$chmodprog 0755" | |
35 | chowncmd="" | |
36 | chgrpcmd="" | |
37 | stripcmd="" | |
38 | rmcmd="$rmprog -f" | |
39 | mvcmd="$mvprog" | |
40 | src="" | |
41 | dst="" | |
42 | dir_arg="" | |
43 | ||
44 | while [ x"$1" != x ]; do | |
45 | case $1 in | |
46 | -c) instcmd="$cpprog" | |
47 | shift | |
48 | continue;; | |
49 | ||
50 | -d) dir_arg=true | |
51 | shift | |
52 | continue;; | |
53 | ||
54 | -m) chmodcmd="$chmodprog $2" | |
55 | shift | |
56 | shift | |
57 | continue;; | |
58 | ||
59 | -o) chowncmd="$chownprog $2" | |
60 | shift | |
61 | shift | |
62 | continue;; | |
63 | ||
64 | -g) chgrpcmd="$chgrpprog $2" | |
65 | shift | |
66 | shift | |
67 | continue;; | |
68 | ||
69 | -s) stripcmd="$stripprog" | |
70 | shift | |
71 | continue;; | |
72 | ||
73 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` | |
74 | shift | |
75 | continue;; | |
76 | ||
77 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` | |
78 | shift | |
79 | continue;; | |
80 | ||
81 | *) if [ x"$src" = x ] | |
82 | then | |
83 | src=$1 | |
84 | else | |
85 | # this colon is to work around a 386BSD /bin/sh bug | |
86 | : | |
87 | dst=$1 | |
88 | fi | |
89 | shift | |
90 | continue;; | |
91 | esac | |
92 | done | |
93 | ||
94 | if [ x"$src" = x ] | |
95 | then | |
96 | echo "install: no input file specified" | |
97 | exit 1 | |
98 | else | |
99 | true | |
100 | fi | |
101 | ||
102 | if [ x"$dir_arg" != x ]; then | |
103 | dst=$src | |
104 | src="" | |
105 | ||
106 | if [ -d $dst ]; then | |
107 | instcmd=: | |
108 | else | |
109 | instcmd=mkdir | |
110 | fi | |
111 | else | |
112 | ||
113 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command | |
114 | # might cause directories to be created, which would be especially bad | |
115 | # if $src (and thus $dsttmp) contains '*'. | |
116 | ||
117 | if [ -f $src -o -d $src ] | |
118 | then | |
119 | true | |
120 | else | |
121 | echo "install: $src does not exist" | |
122 | exit 1 | |
123 | fi | |
124 | ||
125 | if [ x"$dst" = x ] | |
126 | then | |
127 | echo "install: no destination specified" | |
128 | exit 1 | |
129 | else | |
130 | true | |
131 | fi | |
132 | ||
133 | # If destination is a directory, append the input filename; if your system | |
134 | # does not like double slashes in filenames, you may need to add some logic | |
135 | ||
136 | if [ -d $dst ] | |
137 | then | |
138 | dst="$dst"/`basename $src` | |
139 | else | |
140 | true | |
141 | fi | |
142 | fi | |
143 | ||
144 | ## this sed command emulates the dirname command | |
145 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | |
146 | ||
147 | # Make sure that the destination directory exists. | |
148 | # this part is taken from Noah Friedman's mkinstalldirs script | |
149 | ||
150 | # Skip lots of stat calls in the usual case. | |
151 | if [ ! -d "$dstdir" ]; then | |
152 | defaultIFS=' | |
153 | ' | |
154 | IFS="${IFS-${defaultIFS}}" | |
155 | ||
156 | oIFS="${IFS}" | |
157 | # Some sh's can't handle IFS=/ for some reason. | |
158 | IFS='%' | |
159 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` | |
160 | IFS="${oIFS}" | |
161 | ||
162 | pathcomp='' | |
163 | ||
164 | while [ $# -ne 0 ] ; do | |
165 | pathcomp="${pathcomp}${1}" | |
166 | shift | |
167 | ||
168 | if [ ! -d "${pathcomp}" ] ; | |
169 | then | |
170 | $mkdirprog "${pathcomp}" | |
171 | else | |
172 | true | |
173 | fi | |
174 | ||
175 | pathcomp="${pathcomp}/" | |
176 | done | |
177 | fi | |
178 | ||
179 | if [ x"$dir_arg" != x ] | |
180 | then | |
181 | $doit $instcmd $dst && | |
182 | ||
183 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && | |
184 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && | |
185 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && | |
186 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi | |
187 | else | |
188 | ||
189 | # If we're going to rename the final executable, determine the name now. | |
190 | ||
191 | if [ x"$transformarg" = x ] | |
192 | then | |
193 | dstfile=`basename $dst` | |
194 | else | |
195 | dstfile=`basename $dst $transformbasename | | |
196 | sed $transformarg`$transformbasename | |
197 | fi | |
198 | ||
199 | # don't allow the sed command to completely eliminate the filename | |
200 | ||
201 | if [ x"$dstfile" = x ] | |
202 | then | |
203 | dstfile=`basename $dst` | |
204 | else | |
205 | true | |
206 | fi | |
207 | ||
208 | # Make a temp file name in the proper directory. | |
209 | ||
210 | dsttmp=$dstdir/#inst.$$# | |
211 | ||
212 | # Move or copy the file name to the temp name | |
213 | ||
214 | $doit $instcmd $src $dsttmp && | |
215 | ||
216 | trap "rm -f ${dsttmp}" 0 && | |
217 | ||
218 | # and set any options; do chmod last to preserve setuid bits | |
219 | ||
220 | # If any of these fail, we abort the whole thing. If we want to | |
221 | # ignore errors from any of these, just make sure not to ignore | |
222 | # errors from the above "$doit $instcmd $src $dsttmp" command. | |
223 | ||
224 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && | |
225 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && | |
226 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && | |
227 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && | |
228 | ||
229 | # Now rename the file to the real destination. | |
230 | ||
231 | $doit $rmcmd -f $dstdir/$dstfile && | |
232 | $doit $mvcmd $dsttmp $dstdir/$dstfile | |
233 | ||
234 | fi && | |
235 | ||
236 | ||
237 | exit 0 |
14 | 14 | rdfs.rdfs dc.rdfs eor.rdfs owl.owl rdf_library.ttl) |
15 | 15 | prepend(SWIPL_SEMWEB_DATA ${CMAKE_CURRENT_SOURCE_DIR} ${SWIPL_SEMWEB_DATA}) |
16 | 16 | |
17 | if(HAVE_LIBATOMIC) | |
18 | set(RDFDB_CLIBS atomic) | |
19 | else() | |
20 | set(RDFDB_CLIBS) | |
21 | endif() | |
22 | ||
17 | 23 | swipl_plugin( |
18 | 24 | rdf_db |
19 | 25 | C_SOURCES rdf_db.c atom.c md5.c atom_map.c debug.c |
20 | 26 | hash.c murmur.c query.c resource.c error.c skiplist.c |
21 | 27 | snapshot.c xsd.c |
22 | C_LIBS | |
28 | C_LIBS ${RDFDB_CLIBS} | |
23 | 29 | PL_LIB_SUBDIR semweb |
24 | 30 | PL_LIBS rdf_db.pl rdfs.pl rdf_edit.pl rdf_litindex.pl |
25 | 31 | rdf_persistency.pl rdf_turtle.pl rdf_cache.pl |
33 | 33 | |
34 | 34 | #ifndef PL_DEFER_FREE_H_INCLUDED |
35 | 35 | #define PL_DEFER_FREE_H_INCLUDED |
36 | #include "memory.h" | |
36 | 37 | |
37 | 38 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
38 | 39 | This header supports freeing data in datastructures that are designed |
127 | 128 | do |
128 | 129 | { o = df->free_cells; |
129 | 130 | last->next = o; |
130 | } while ( !__sync_bool_compare_and_swap(&df->free_cells, o, list) ); | |
131 | } while ( !COMPARE_AND_SWAP_PTR(&df->free_cells, o, list) ); | |
131 | 132 | } |
132 | 133 | |
133 | 134 | |
147 | 148 | } else |
148 | 149 | return NULL; |
149 | 150 | } |
150 | } while ( !__sync_bool_compare_and_swap(&df->free_cells, c, c->next) ); | |
151 | } while ( !COMPARE_AND_SWAP_PTR(&df->free_cells, c, c->next) ); | |
151 | 152 | |
152 | 153 | return c; |
153 | 154 | } |
167 | 168 | do |
168 | 169 | { o = df->freed; |
169 | 170 | c->next = o; |
170 | } while ( !__sync_bool_compare_and_swap(&df->freed, o, c) ); | |
171 | } while ( !COMPARE_AND_SWAP_PTR(&df->freed, o, c) ); | |
171 | 172 | } |
172 | 173 | |
173 | 174 | |
185 | 186 | do |
186 | 187 | { o = df->freed; |
187 | 188 | c->next = o; |
188 | } while ( !__sync_bool_compare_and_swap(&df->freed, o, c) ); | |
189 | } while ( !COMPARE_AND_SWAP_PTR(&df->freed, o, c) ); | |
189 | 190 | } |
190 | 191 | |
191 | 192 | |
192 | 193 | |
193 | 194 | static inline void |
194 | 195 | enter_scan(defer_free *df) |
195 | { __sync_add_and_fetch(&df->active, 1); | |
196 | { ATOMIC_INC(&df->active); | |
196 | 197 | } |
197 | 198 | |
198 | 199 | |
200 | 201 | exit_scan(defer_free *df) |
201 | 202 | { defer_cell *o = df->freed; |
202 | 203 | |
203 | if ( __sync_sub_and_fetch(&df->active, 1) == 0 ) | |
204 | { if ( o && __sync_bool_compare_and_swap(&df->freed, o, NULL) ) | |
204 | if ( ATOMIC_DEC(&df->active) == 0 ) | |
205 | { if ( o && COMPARE_AND_SWAP_PTR(&df->freed, o, NULL) ) | |
205 | 206 | { defer_cell *fl = o; |
206 | 207 | |
207 | 208 | for(;;) |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2011-2013, VU University Amsterdam | |
5 | Copyright (c) 2011-2020, VU University Amsterdam | |
6 | 6 | All rights reserved. |
7 | 7 | |
8 | 8 | Redistribution and use in source and binary forms, with or without |
32 | 32 | */ |
33 | 33 | |
34 | 34 | #include "rdf_db.h" |
35 | #include "memory.h" | |
35 | 36 | |
36 | 37 | |
37 | 38 | /******************************* |
77 | 78 | |
78 | 79 | |
79 | 80 | typedef struct prefix_cache |
80 | { atom_t local; | |
81 | atom_t alias; | |
82 | atom_t uri; | |
83 | int generation; | |
84 | int locked; | |
81 | { atom_t local; | |
82 | atom_t alias; | |
83 | atom_t uri; | |
84 | int generation; | |
85 | unsigned int locked; | |
85 | 86 | } prefix_cache; |
86 | 87 | |
87 | 88 | #define PREFIX_EXPAND_ENTRIES 4 |
113 | 114 | for(i=(++cache_ptr%PREFIX_EXPAND_ENTRIES); ; i = (i+1)%PREFIX_EXPAND_ENTRIES) |
114 | 115 | { prefix_cache *c = &cache[i]; |
115 | 116 | |
116 | if ( __sync_bool_compare_and_swap(&c->locked, 0, 1) ) | |
117 | if ( COMPARE_AND_SWAP_UINT(&c->locked, 0, 1) ) | |
117 | 118 | { atom_t olocal = c->local; |
118 | 119 | atom_t ouri = c->uri; |
119 | 120 | |
145 | 146 | for( i=0; i<PREFIX_EXPAND_ENTRIES; i++) |
146 | 147 | { prefix_cache *c = &cache[i]; |
147 | 148 | |
148 | while( !__sync_bool_compare_and_swap(&c->locked, 0, 1) ) | |
149 | ; | |
149 | while( !COMPARE_AND_SWAP_UINT(&c->locked, 0, 1) ) | |
150 | ; /* spin lock */ | |
150 | 151 | |
151 | 152 | { atom_t olocal = c->local; |
152 | 153 | atom_t ouri = c->uri; |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2011-2013, VU University Amsterdam | |
5 | Copyright (c) 2011-2020, VU University Amsterdam | |
6 | CWI, Amsterdam | |
6 | 7 | All rights reserved. |
7 | 8 | |
8 | 9 | Redistribution and use in source and binary forms, with or without |
80 | 81 | #elif defined(__GNUC__) /* GCC version */ |
81 | 82 | |
82 | 83 | #define MSB(i) ((i) ? (32 - __builtin_clz(i)) : 0) |
83 | #define MEMORY_BARRIER() __sync_synchronize() | |
84 | #define MEMORY_BARRIER() __atomic_thread_fence(__ATOMIC_SEQ_CST) | |
84 | 85 | #define PREFETCH_FOR_WRITE(p) __builtin_prefetch(p, 1, 0) |
85 | 86 | #define PREFETCH_FOR_READ(p) __builtin_prefetch(p, 0, 0) |
86 | #define ATOMIC_ADD(ptr, v) __sync_add_and_fetch(ptr, v) | |
87 | #define ATOMIC_SUB(ptr, v) __sync_sub_and_fetch(ptr, v) | |
87 | #define ATOMIC_ADD(ptr, v) __atomic_add_fetch(ptr, v, __ATOMIC_SEQ_CST) | |
88 | #define ATOMIC_SUB(ptr, v) __atomic_sub_fetch(ptr, v, __ATOMIC_SEQ_CST) | |
88 | 89 | #define ATOMIC_INC(ptr) ATOMIC_ADD(ptr, 1) /* ++(*ptr) */ |
89 | 90 | #define ATOMIC_DEC(ptr) ATOMIC_SUB(ptr, 1) /* --(*ptr) */ |
91 | ||
92 | #define __COMPARE_AND_SWAP(at, from, to) \ | |
93 | __atomic_compare_exchange_n(at, &(from), to, FALSE, \ | |
94 | __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) | |
95 | ||
96 | static inline int | |
97 | COMPARE_AND_SWAP_PTR(void *at, void *from, void *to) | |
98 | { void **ptr = at; | |
99 | ||
100 | return __COMPARE_AND_SWAP(ptr, from, to); | |
101 | } | |
102 | ||
103 | static inline int | |
104 | COMPARE_AND_SWAP_UINT(unsigned int *at, unsigned int from, unsigned int to) | |
105 | { return __COMPARE_AND_SWAP(at, from, to); | |
106 | } | |
107 | ||
90 | 108 | |
91 | 109 | #endif /*_MSC_VER|__GNUC__*/ |
92 | 110 |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2003-2016, University of Amsterdam | |
5 | Copyright (c) 2003-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
1088 | 1088 | do |
1089 | 1089 | { o = a->freelist; |
1090 | 1090 | last->fnext = o; |
1091 | } while ( !__sync_bool_compare_and_swap(&a->freelist, o, list) ); | |
1091 | } while ( !COMPARE_AND_SWAP_PTR(&a->freelist, o, list) ); | |
1092 | 1092 | } |
1093 | 1093 | |
1094 | 1094 | static int |
1164 | 1164 | resize_triple_array(db); |
1165 | 1165 | simpleMutexUnlock(&db->locks.misc); |
1166 | 1166 | } |
1167 | } while ( !__sync_bool_compare_and_swap(&a->freelist, e, e->fnext) ); | |
1167 | } while ( !COMPARE_AND_SWAP_PTR(&a->freelist, e, e->fnext) ); | |
1168 | 1168 | |
1169 | 1169 | e->triple = t; |
1170 | 1170 |
579 | 579 | rdf_meta_specification(G, IM, Spec), |
580 | 580 | rdf_expand(G, Spec, Expanded, LM). |
581 | 581 | |
582 | system:term_expansion(Module:Fact, Expanded) :- | |
583 | atom(Module), | |
584 | rdf_meta_specification(Fact, Module, Spec), | |
585 | rdf_expand(Fact, Spec, ExpandedFact, Module), | |
586 | Fact \== ExpandedFact, | |
587 | Expanded = (Module:ExpandedFact). | |
582 | 588 | system:term_expansion(Fact, Expanded) :- |
583 | 589 | prolog_load_context(module, Module), |
584 | 590 | rdf_meta_specification(Fact, Module, Spec), |
585 | 591 | rdf_expand(Fact, Spec, Expanded, Module), |
586 | 592 | Fact \== Expanded. |
593 | system:term_expansion((Module:Head :- Body), (Expanded :- Body)) :- | |
594 | atom(Module), | |
595 | rdf_meta_specification(Head, Module, Spec), | |
596 | rdf_expand(Head, Spec, ExpandedHead, Module), | |
597 | Head \== ExpandedHead, | |
598 | Expanded = (Module:ExpandedHead). | |
587 | 599 | system:term_expansion((Head :- Body), (Expanded :- Body)) :- |
588 | 600 | prolog_load_context(module, Module), |
589 | 601 | rdf_meta_specification(Head, Module, Spec), |
38 | 38 | #include <string.h> |
39 | 39 | #include <stdlib.h> |
40 | 40 | #include "skiplist.h" |
41 | #include "memory.h" | |
41 | 42 | |
42 | 43 | static int debuglevel; |
43 | 44 | |
86 | 87 | { n0 = next; |
87 | 88 | |
88 | 89 | n = n0 * 1103515245 + 12345; |
89 | } while(n != n0 && !__sync_bool_compare_and_swap(&next, n0, n)); | |
90 | } while(n != n0 && !COMPARE_AND_SWAP_UINT(&next, n0, n)); | |
90 | 91 | |
91 | 92 | return((unsigned int)(n/65536) % 32768); |
92 | 93 | } |
93 | 93 | % modifications on g2 (in a snapshot). |
94 | 94 | |
95 | 95 | test(N) :- |
96 | test(g1, N). | |
96 | test(-, N). | |
97 | 97 | |
98 | 98 | test(G, N*M) :- |
99 | 99 | !, |
262 | 262 | :- dynamic |
263 | 263 | record_stream/2. % Graph, Out |
264 | 264 | |
265 | record_in(-, -) :- | |
266 | !. | |
265 | 267 | record_in(Graph, Out) :- |
266 | 268 | file_name_extension(Graph, rec, File), |
267 | 269 | open(File, write, Out), |
25 | 25 | PL_LIBS ${DTD_FILES} |
26 | 26 | THREADED) |
27 | 27 | |
28 | test_libs(sgml sgml_write xsd | |
29 | TEST_DIRS Test) | |
28 | test_libs(sgml sgml_write xsd c14n | |
29 | TEST_DIRS Test testdata) | |
30 | 30 | |
31 | 31 | pkg_doc(sgml |
32 | 32 | SECTION |
152 | 152 | put_elemns(Name, CName, InNS, OutNS0, OutNS, []) :- |
153 | 153 | put_ns(Name, CName, InNS, OutNS0, OutNS). |
154 | 154 | |
155 | put_ns(ns('', xml):Name, xml:Name, _InNS, OutNS, OutNS) :- | |
156 | !. | |
155 | 157 | put_ns(ns(NS, URL):Name, CName, _InNS, OutNS, OutNS) :- |
156 | 158 | get_dict(URL, OutNS, NS), |
157 | 159 | !, |
671 | 671 | |
672 | 672 | add_missing_ns([], Atts, Atts). |
673 | 673 | add_missing_ns([H|T], Atts0, Atts) :- |
674 | generate_ns(H, NS), | |
675 | add_missing_ns(T, [xmlns:NS=H|Atts0], Atts). | |
676 | ||
677 | %! generate_ns(+URI, -NS) is det. | |
674 | generate_ns(H, NS, URL), | |
675 | add_missing_ns(T, [xmlns:NS=URL|Atts0], Atts). | |
676 | ||
677 | %! generate_ns(+URI, -NS, -URL) is det. | |
678 | 678 | % |
679 | 679 | % Generate a namespace (NS) identifier for URI. |
680 | 680 | |
681 | generate_ns(URI, NS) :- | |
681 | generate_ns(URI, NS, URI) :- | |
682 | 682 | xmlns(NS, URI), |
683 | 683 | !. |
684 | generate_ns(URI, NS) :- | |
684 | generate_ns(ns(NS, URI), NS, URI) :- | |
685 | !. | |
686 | generate_ns(URI, NS, URI) :- | |
685 | 687 | default_ns(URI, NS), |
686 | 688 | !. |
687 | generate_ns(_, NS) :- | |
689 | generate_ns(URI, NS, URI) :- | |
688 | 690 | gensym(xns, NS). |
689 | 691 | |
690 | 692 | %! xmlns(?NS, ?URI) is nondet. |
745 | 747 | |
746 | 748 | missing_ns(ns(NS, URI):_, Def, M0, M) :- |
747 | 749 | !, |
748 | ( memberchk(NS=URI, Def) | |
750 | ( ( memberchk(NS=URI, Def) | |
751 | ; memberchk(NS=URI, M0) | |
752 | ) | |
749 | 753 | -> M = M0 |
750 | 754 | ; NS == '' |
751 | 755 | -> M = M0 |
752 | ; M = [URI|M0] | |
756 | ; M = [ns(NS, URI)|M0] | |
753 | 757 | ). |
754 | 758 | missing_ns(URI:_, Def, M0, M) :- |
755 | 759 | !, |
0 | /* Part of SWI-Prolog | |
1 | ||
2 | Author: Matt Lilley | |
3 | E-mail: matt.lilley@securitease.com | |
4 | WWW: http://www.swi-prolog.org | |
5 | Copyright (c) 2013-2020, University of Amsterdam | |
6 | VU University Amsterdam | |
7 | CWI, Amsterdam | |
8 | All rights reserved. | |
9 | ||
10 | Redistribution and use in source and binary forms, with or without | |
11 | modification, are permitted provided that the following conditions | |
12 | are met: | |
13 | ||
14 | 1. Redistributions of source code must retain the above copyright | |
15 | notice, this list of conditions and the following disclaimer. | |
16 | ||
17 | 2. Redistributions in binary form must reproduce the above copyright | |
18 | notice, this list of conditions and the following disclaimer in | |
19 | the documentation and/or other materials provided with the | |
20 | distribution. | |
21 | ||
22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
23 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
25 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
26 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
27 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
28 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
30 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
31 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
32 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
33 | POSSIBILITY OF SUCH DAMAGE. | |
34 | */ | |
35 | ||
36 | :- module(test_c14n, | |
37 | [ test_c14n/0 | |
38 | ]). | |
39 | ||
40 | :- use_module(library(c14n2)). | |
41 | ||
42 | test_c14n :- | |
43 | run_tests([ c14n ]). | |
44 | ||
45 | :-begin_tests(c14n). | |
46 | ||
47 | ||
48 | %! xml_file(+File, -Absolute) | |
49 | % | |
50 | % Find an absolute path to the xml sample data in the `testdata` directory. | |
51 | ||
52 | xml_file(File, Abs) :- | |
53 | source_file(xml_file(_,_), MyFile), | |
54 | file_directory_name(MyFile, MyDir), | |
55 | atomic_list_concat([MyDir, File], /, Abs). | |
56 | ||
57 | %! c14n_test(+InputFile, +XPath, +TargetFile). | |
58 | % | |
59 | % Canonicalize the document obtained by applying the XPath specification to | |
60 | % the document specified by InputFile and confirm it matches exactly the | |
61 | % bytes in TargetFile. | |
62 | % The XPath specification is a shorthand for logic that a built-in XPath | |
63 | % expression cannot directly express | |
64 | ||
65 | c14n_test(InputFile, XPathSpec, TargetFile):- | |
66 | xml_file(InputFile, InputFilename), | |
67 | xml_file(TargetFile, TargetFilename), | |
68 | setup_call_cleanup(open(InputFilename, read, InputStream), | |
69 | load_structure(InputStream, InputDocument, [dialect(xmlns), space(preserve), keep_prefix(true)]), | |
70 | close(InputStream)), | |
71 | setup_call_cleanup(open(TargetFilename, read, TargetStream), | |
72 | read_string(TargetStream, _, TargetDocument), | |
73 | close(TargetStream)), | |
74 | findall(SubDocument, | |
75 | extract_subdocument(InputDocument, XPathSpec, SubDocument), | |
76 | SubDocuments), | |
77 | with_output_to(string(GeneratedDocument), | |
78 | forall(member(SubDocument, SubDocuments), | |
79 | xml_write_canonical(current_output, SubDocument, [method('http://www.w3.org/2001/10/xml-exc-c14n#')]))), | |
80 | %format(user_error, '~w~n~n', [GeneratedDocument]), | |
81 | TargetDocument == GeneratedDocument. | |
82 | ||
83 | extract_subdocument(InputDocument, (A ; B), SubDocument):- | |
84 | !, | |
85 | ( extract_subdocument(InputDocument, A, SubDocument) | |
86 | ; extract_subdocument(InputDocument, B, SubDocument) | |
87 | ). | |
88 | ||
89 | extract_subdocument(InputDocument, (A, \+B), SubDocument):- | |
90 | !, | |
91 | extract_subdocument(InputDocument, A, Intermediate), | |
92 | delete_subdocument([Intermediate], B, [SubDocument]). | |
93 | ||
94 | extract_subdocument(InputDocument, ElementName, SubDocument):- | |
95 | xpath(InputDocument, //(_:ElementName), SubDocument). | |
96 | ||
97 | delete_subdocument(Document, (A ; B), SubDocument):- | |
98 | !, | |
99 | delete_subdocument(Document, A, S1), | |
100 | delete_subdocument(S1, B, SubDocument). | |
101 | ||
102 | delete_subdocument([], _, []):- !. | |
103 | ||
104 | delete_subdocument(Document, Element, Document):- | |
105 | % Nothing to do - fail quickly | |
106 | \+xpath_chk(Document, //(_:Element), _), | |
107 | !. | |
108 | ||
109 | delete_subdocument([element(_:Element, _, _)|Siblings], Element, NewSiblings):- | |
110 | !, | |
111 | delete_subdocument(Siblings, Element, NewSiblings). | |
112 | ||
113 | delete_subdocument([element(NS:OtherElement, Attributes, Children)|Siblings], Element, [element(NS:OtherElement, Attributes, NewChildren)|NewSiblings]):- | |
114 | !, | |
115 | delete_subdocument(Children, Element, NewChildren), | |
116 | delete_subdocument(Siblings, Element, NewSiblings). | |
117 | ||
118 | delete_subdocument([Atom|Siblings], Element, [Atom|NewSiblings]):- | |
119 | delete_subdocument(Siblings, Element, NewSiblings). | |
120 | ||
121 | ||
122 | ||
123 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
124 | These tests are derived from the w3c tests available at | |
125 | https://www.w3.org/TR/xmldsig2ed-tests/#TestCases-C14n11 | |
126 | The input/target documents are stored in testdata/ | |
127 | The xpath expressions are encoded inline in the tests. This is because the | |
128 | SWI-Prolog implementation of xpath is not syntax-compatible with the w3c one | |
129 | The test names include the section of the source document they pertain to | |
130 | Note that the tests originally are for xml-c14n and not xml-c14n-exc | |
131 | I have extracted the equivalent *-exc.output documents using xmlstarlet and | |
132 | the appropriate xpath files | |
133 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
134 | ||
135 | test('3.2.1.1 Test case c14n11/xmllang-1'):- | |
136 | c14n_test('testdata/xmllang-input.xml', e1, 'testdata/xmllang-1-exc.output'). | |
137 | ||
138 | test('3.2.1.2 Test case c14n11/xmllang-2'):- | |
139 | c14n_test('testdata/xmllang-input.xml', e2, 'testdata/xmllang-2-exc.output'). | |
140 | ||
141 | test('3.2.1.3 Test case c14n11/xmllang-3'):- | |
142 | c14n_test('testdata/xmllang-input.xml', e11, 'testdata/xmllang-3-exc.output'). | |
143 | ||
144 | test('3.2.1.4 Test case c14n11/xmllang-4'):- | |
145 | c14n_test('testdata/xmllang-input.xml', (e11 ; e12), 'testdata/xmllang-4-exc.output'). | |
146 | ||
147 | % These 4 tests all produce an SGML warning that xml:space="true" is invalid | |
148 | % It is indeed invalid, but that is what is in the official input document | |
149 | test('3.2.2.1 Test case c14n11/xmlspace-1'):- | |
150 | c14n_test('testdata/xmlspace-input.xml', e1, 'testdata/xmlspace-1-exc.output'). | |
151 | ||
152 | test('3.2.2.2 Test case c14n11/xmlspace-2'):- | |
153 | c14n_test('testdata/xmlspace-input.xml', e2, 'testdata/xmlspace-2-exc.output'). | |
154 | ||
155 | test('3.2.2.3 Test case c14n11/xmlspace-3'):- | |
156 | c14n_test('testdata/xmlspace-input.xml', e11, 'testdata/xmlspace-3-exc.output'). | |
157 | ||
158 | test('3.2.2.4 Test case c14n11/xmlspace-4'):- | |
159 | c14n_test('testdata/xmlspace-input.xml', (e11 ; e12), 'testdata/xmlspace-4-exc.output'). | |
160 | ||
161 | test('3.2.3.1 Test case c14n11/xmlid-1'):- | |
162 | c14n_test('testdata/xmlid-input.xml', e1, 'testdata/xmlid-1-exc.output'). | |
163 | ||
164 | test('3.2.3.2 Test case c14n11/xmlid-2'):- | |
165 | c14n_test('testdata/xmlid-input.xml', (e11 ; e12), 'testdata/xmlid-2-exc.output'). | |
166 | ||
167 | test('3.2.4.1,1 Test case c14n11/xmlbase-prop-1'):- | |
168 | c14n_test('testdata/xmlbase-prop-input.xml', (c14n11XmlBaseDoc1, \+e2), 'testdata/xmlbase-prop-1-exc.output'). | |
169 | ||
170 | test('3.2.4.1.2 Test case c14n11/xmlbase-prop-2'):- | |
171 | c14n_test('testdata/xmlbase-prop-input.xml', e1, 'testdata/xmlbase-prop-2-exc.output'). | |
172 | ||
173 | test('3.2.4.1.3 Test case c14n11/xmlbase-prop-3'):- | |
174 | c14n_test('testdata/xmlbase-prop-input.xml', e11, 'testdata/xmlbase-prop-3-exc.output'). | |
175 | ||
176 | test('3.2.4.1.4 Test case c14n11/xmlbase-prop-4'):- | |
177 | c14n_test('testdata/xmlbase-prop-input.xml', e111, 'testdata/xmlbase-prop-4-exc.output'). | |
178 | ||
179 | test('3.2.4.1.5 Test case c14n11/xmlbase-prop-5'):- | |
180 | c14n_test('testdata/xmlbase-prop-input.xml', e21, 'testdata/xmlbase-prop-5-exc.output'). | |
181 | ||
182 | test('3.2.4.1.6 Test case c14n11/xmlbase-prop-6'):- | |
183 | c14n_test('testdata/xmlbase-prop-input.xml', e3, 'testdata/xmlbase-prop-6-exc.output'). | |
184 | ||
185 | test('3.2.4.1.7 Test case c14n11/xmlbase-prop-7'):- | |
186 | c14n_test('testdata/xmlbase-prop-input.xml', (c14n11XmlBaseDoc1, \+(e1 ; e2)), 'testdata/xmlbase-prop-7-exc.output'). | |
187 | ||
188 | test('3.2.4.2.1 Test case c14n11/xmlbase-c14n11spec-102', [blocked('Cannot express [self::ietf:e1 or (parent::ietf:e1 and not(self::text() or self::e2)) or count(id("E3")|ancestor-or-self::node()) = count(ancestor-or-self::node())] using builtin xpath')]):- | |
189 | c14n_test('testdata/xmlbase-c14n11spec-input.xml', unknown, 'xmlbase-c14n11spec-102.output'). | |
190 | ||
191 | test('3.2.4.2.2 Test case c14n11/xmlbase-c14n11spec-102', [blocked('Cannot express [self::ietf:e1 or (parent::ietf:e1 and not(self::text() or self::e2)) or count(id("E3")|ancestor-or-self::node()) = count(ancestor-or-self::node())] using builtin xpath')]):- | |
192 | c14n_test('testdata/xmlbase-c14n11spec2-input.xml', unknown, 'xmlbase-c14n11spec2-102.output'). | |
193 | ||
194 | test('3.2.4.2.3 Test case c14n11/xmlbase-c14n11spec-102', [blocked('Cannot express [self::a or ancestor-or-self::d] using builtin xpath')]):- | |
195 | c14n_test('testdata/xmlbase-c14n11spec3-input.xml', unknown 'xmlbase-c14n11spec3-102.output'). | |
196 | ||
197 | ||
198 | :-end_tests(c14n).⏎ |
4 | 4 | user:file_search_path(library, '../plunit'). |
5 | 5 | |
6 | 6 | :- use_module(library(sgml)). |
7 | :- use_module(library(apply)). | |
7 | 8 | :- use_module(library(debug)). |
8 | 9 | :- use_module(library(plunit)). |
9 | 10 |
0 | <e1 xmlns="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:base="http://www.example.com/something/else"><e3 xmlns="" id="E3" xml:base="../bar/foo" xml:space="preserve"></e3></e1>⏎ |
0 | <!DOCTYPE doc [ | |
1 | <!ATTLIST e2 xml:space (default|preserve) 'preserve'> | |
2 | <!ATTLIST e3 id ID #IMPLIED> | |
3 | ]> | |
4 | <doc xmlns="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:base="http://www.example.com/something/else"> | |
5 | <e1> | |
6 | <e2 xmlns="" xml:id="abc" xml:base="../bar/"> | |
7 | <e3 id="E3" xml:base="foo"/> | |
8 | </e2> | |
9 | </e1> | |
10 | </doc>⏎ |
0 | <e1 xmlns="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:base="something/else"><e3 xmlns="" id="E3" xml:base="bar/foo" xml:space="preserve"></e3></e1>⏎ |
0 | <!DOCTYPE doc [ | |
1 | <!ATTLIST e2 xml:space (default|preserve) 'preserve'> | |
2 | <!ATTLIST e3 id ID #IMPLIED> | |
3 | ]> | |
4 | <doc xmlns="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:base="something/else"> | |
5 | <e1> | |
6 | <e2 xmlns="" xml:id="abc" xml:base="bar/"> | |
7 | <e3 id="E3" xml:base="foo"/> | |
8 | </e2> | |
9 | </e1> | |
10 | </doc>⏎ |
0 | <?xml version="1.0" encoding="UTF-8"?> | |
1 | <a xml:base="foo/bar"> | |
2 | <b xml:base=".."> | |
3 | <c xml:base=".."> | |
4 | <d xml:base="x"> | |
5 | </d> | |
6 | </c> | |
7 | </b> | |
8 | </a> |
0 | <ietf:c14n11XmlBaseDoc1 xmlns:ietf="http://www.ietf.org" xml:base="http://xmlbase.example.org/xmlbase0/"> | |
1 | <ietf:e1 xml:base="/xmlbase1/"> | |
2 | <ietf:e11 xml:base="/xmlbase11/"> | |
3 | <ietf:e111 xml:base="/xmlbase111/"></ietf:e111> | |
4 | </ietf:e11> | |
5 | <ietf:e12 at="2"> | |
6 | <ietf:e121 xml:base="/xmlbase121/"></ietf:e121> | |
7 | </ietf:e12> | |
8 | </ietf:e1> | |
9 | ||
10 | <ietf:e3> | |
11 | <ietf:e31 at="3"></ietf:e31> | |
12 | </ietf:e3> | |
13 | </ietf:c14n11XmlBaseDoc1>⏎ |
0 | <ietf:c14n11XmlBaseDoc1 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:base="http://xmlbase.example.org/xmlbase0/"> | |
1 | <ietf:e1 xml:base="/xmlbase1/"> | |
2 | <ietf:e11 xml:base="/xmlbase11/"> | |
3 | <ietf:e111 xml:base="/xmlbase111/"></ietf:e111> | |
4 | </ietf:e11> | |
5 | <ietf:e12 at="2"> | |
6 | <ietf:e121 xml:base="/xmlbase121/"></ietf:e121> | |
7 | </ietf:e12> | |
8 | </ietf:e1> | |
9 | ||
10 | <ietf:e3> | |
11 | <ietf:e31 at="3"></ietf:e31> | |
12 | </ietf:e3> | |
13 | </ietf:c14n11XmlBaseDoc1>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:c14n11XmlBaseDoc1 and not(ancestor-or-self::ietf:e2)]</XPath>⏎ |
0 | <ietf:e1 xmlns:ietf="http://www.ietf.org" xml:base="/xmlbase1/"> | |
1 | <ietf:e11 xml:base="/xmlbase11/"> | |
2 | <ietf:e111 xml:base="/xmlbase111/"></ietf:e111> | |
3 | </ietf:e11> | |
4 | <ietf:e12 at="2"> | |
5 | <ietf:e121 xml:base="/xmlbase121/"></ietf:e121> | |
6 | </ietf:e12> | |
7 | </ietf:e1>⏎ |
0 | <ietf:e1 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:base="http://xmlbase.example.org/xmlbase1/"> | |
1 | <ietf:e11 xml:base="/xmlbase11/"> | |
2 | <ietf:e111 xml:base="/xmlbase111/"></ietf:e111> | |
3 | </ietf:e11> | |
4 | <ietf:e12 at="2"> | |
5 | <ietf:e121 xml:base="/xmlbase121/"></ietf:e121> | |
6 | </ietf:e12> | |
7 | </ietf:e1>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:e1]</XPath>⏎ |
0 | <ietf:e11 xmlns:ietf="http://www.ietf.org" xml:base="/xmlbase11/"> | |
1 | <ietf:e111 xml:base="/xmlbase111/"></ietf:e111> | |
2 | </ietf:e11>⏎ |
0 | <ietf:e11 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:base="http://xmlbase.example.org/xmlbase11/"> | |
1 | <ietf:e111 xml:base="/xmlbase111/"></ietf:e111> | |
2 | </ietf:e11>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:e11]</XPath>⏎ |
0 | <ietf:e111 xmlns:ietf="http://www.ietf.org" xml:base="/xmlbase111/"></ietf:e111>⏎ |
0 | <ietf:e111 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:base="http://xmlbase.example.org/xmlbase111/"></ietf:e111>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:e111]</XPath>⏎ |
0 | <ietf:e21 xmlns:ietf="http://www.ietf.org" xml:base="/xmlbase21/"></ietf:e21>⏎ |
0 | <ietf:e21 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:base="http://xmlbase.example.org/xmlbase21/"></ietf:e21>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:e21]</XPath>⏎ |
0 | <ietf:e3 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:base="http://xmlbase.example.org/xmlbase0/"> | |
1 | <ietf:e31 at="3"></ietf:e31> | |
2 | </ietf:e3>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:e3]</XPath>⏎ |
0 | <ietf:c14n11XmlBaseDoc1 xmlns:ietf="http://www.ietf.org" xml:base="http://xmlbase.example.org/xmlbase0/"> | |
1 | ||
2 | ||
3 | <ietf:e3> | |
4 | <ietf:e31 at="3"></ietf:e31> | |
5 | </ietf:e3> | |
6 | </ietf:c14n11XmlBaseDoc1>⏎ |
0 | <ietf:c14n11XmlBaseDoc1 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:base="http://xmlbase.example.org/xmlbase0/"> | |
1 | ||
2 | ||
3 | <ietf:e3> | |
4 | <ietf:e31 at="3"></ietf:e31> | |
5 | </ietf:e3> | |
6 | </ietf:c14n11XmlBaseDoc1>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:c14n11XmlBaseDoc1 and not(ancestor-or-self::ietf:e1 or ancestor-or-self::ietf:e2)]</XPath>⏎ |
0 | <?xml version="1.0" encoding="UTF-8"?> | |
1 | <ietf:c14n11XmlBaseDoc1 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:base="http://xmlbase.example.org/xmlbase0/"> | |
2 | <ietf:e1 xml:base="/xmlbase1/"> | |
3 | <ietf:e11 xml:base="/xmlbase11/"> | |
4 | <ietf:e111 xml:base="/xmlbase111/"/> | |
5 | </ietf:e11> | |
6 | <ietf:e12 at="2"> | |
7 | <ietf:e121 xml:base="/xmlbase121/"/> | |
8 | </ietf:e12> | |
9 | </ietf:e1> | |
10 | <ietf:e2> | |
11 | <ietf:e21 xml:base="/xmlbase21/"/> | |
12 | </ietf:e2> | |
13 | <ietf:e3> | |
14 | <ietf:e31 at="3"/> | |
15 | </ietf:e3> | |
16 | </ietf:c14n11XmlBaseDoc1> |
0 | <ietf:e1 xmlns:ietf="http://www.ietf.org" xml:id="IdInterop"> | |
1 | <ietf:e11> | |
2 | <ietf:e111></ietf:e111> | |
3 | </ietf:e11> | |
4 | <ietf:e12 at="2"> | |
5 | <ietf:e121></ietf:e121> | |
6 | </ietf:e12> | |
7 | </ietf:e1>⏎ |
0 | <ietf:e1 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:id="IdInterop"> | |
1 | <ietf:e11> | |
2 | <ietf:e111></ietf:e111> | |
3 | </ietf:e11> | |
4 | <ietf:e12 at="2"> | |
5 | <ietf:e121></ietf:e121> | |
6 | </ietf:e12> | |
7 | </ietf:e1>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:e1]</XPath>⏎ |
0 | <ietf:e11 xmlns:ietf="http://www.ietf.org"> | |
1 | <ietf:e111></ietf:e111> | |
2 | </ietf:e11><ietf:e12 xmlns:ietf="http://www.ietf.org" at="2"> | |
3 | <ietf:e121></ietf:e121> | |
4 | </ietf:e12>⏎ |
0 | <ietf:e11 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org"> | |
1 | <ietf:e111></ietf:e111> | |
2 | </ietf:e11><ietf:e12 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" at="2"> | |
3 | <ietf:e121></ietf:e121> | |
4 | </ietf:e12>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:e11 or ancestor-or-self::ietf:e12]</XPath>⏎ |
0 | <?xml version="1.0" encoding="UTF-8"?> | |
1 | <ietf:c14n11XmlIdDoc1 xmlns:ietf="http://www.ietf.org" | |
2 | xmlns:w3c="http://www.w3.org"> | |
3 | <ietf:e1 xml:id="IdInterop"> | |
4 | <ietf:e11> | |
5 | <ietf:e111 /> | |
6 | </ietf:e11> | |
7 | <ietf:e12 at="2"> | |
8 | <ietf:e121 /> | |
9 | </ietf:e12> | |
10 | </ietf:e1> | |
11 | <ietf:e2 > | |
12 | <ietf:e21 /> | |
13 | </ietf:e2> | |
14 | </ietf:c14n11XmlIdDoc1>⏎ |
0 | <ietf:e1 xmlns:ietf="http://www.ietf.org" xml:lang="EN"> | |
1 | <ietf:e11> | |
2 | <ietf:e111></ietf:e111> | |
3 | </ietf:e11> | |
4 | <ietf:e12 at="2"> | |
5 | <ietf:e121></ietf:e121> | |
6 | </ietf:e12> | |
7 | </ietf:e1>⏎ |
0 | <ietf:e1 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:lang="EN"> | |
1 | <ietf:e11> | |
2 | <ietf:e111></ietf:e111> | |
3 | </ietf:e11> | |
4 | <ietf:e12 at="2"> | |
5 | <ietf:e121></ietf:e121> | |
6 | </ietf:e12> | |
7 | </ietf:e1>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*)[ancestor-or-self::ietf:e1]</XPath>⏎ |
0 | <ietf:e2 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org"> | |
1 | <ietf:e21></ietf:e21> | |
2 | </ietf:e2>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*)[ancestor-or-self::ietf:e2]</XPath>⏎ |
0 | <ietf:e11 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:lang="EN"> | |
1 | <ietf:e111></ietf:e111> | |
2 | </ietf:e11>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*)[ancestor-or-self::ietf:e11]</XPath>⏎ |
0 | <ietf:e11 xmlns:ietf="http://www.ietf.org"> | |
1 | <ietf:e111></ietf:e111> | |
2 | </ietf:e11><ietf:e12 xmlns:ietf="http://www.ietf.org" at="2"> | |
3 | <ietf:e121></ietf:e121> | |
4 | </ietf:e12>⏎ |
0 | <ietf:e11 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:lang="EN"> | |
1 | <ietf:e111></ietf:e111> | |
2 | </ietf:e11><ietf:e12 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" at="2" xml:lang="EN"> | |
3 | <ietf:e121></ietf:e121> | |
4 | </ietf:e12>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*)[ancestor-or-self::ietf:e11 or ancestor-or-self::ietf:e12]</XPath>⏎ |
0 | <?xml version="1.0" encoding="UTF-8"?> | |
1 | <ietf:c14n11Xmllang xmlns:ietf="http://www.ietf.org" | |
2 | xmlns:w3c="http://www.w3.org"> | |
3 | <ietf:e1 xml:lang="EN"> | |
4 | <ietf:e11> | |
5 | <ietf:e111 /> | |
6 | </ietf:e11> | |
7 | <ietf:e12 at="2"> | |
8 | <ietf:e121 /> | |
9 | </ietf:e12> | |
10 | </ietf:e1> | |
11 | <ietf:e2 > | |
12 | <ietf:e21 /> | |
13 | </ietf:e2> | |
14 | </ietf:c14n11Xmllang>⏎ |
0 | <ietf:e1 xmlns:ietf="http://www.ietf.org" xml:space="true"> | |
1 | <ietf:e11> | |
2 | <ietf:e111></ietf:e111> | |
3 | </ietf:e11> | |
4 | <ietf:e12 at="2"> | |
5 | <ietf:e121></ietf:e121> | |
6 | </ietf:e12> | |
7 | </ietf:e1>⏎ |
0 | <ietf:e1 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:space="true"> | |
1 | <ietf:e11> | |
2 | <ietf:e111></ietf:e111> | |
3 | </ietf:e11> | |
4 | <ietf:e12 at="2"> | |
5 | <ietf:e121></ietf:e121> | |
6 | </ietf:e12> | |
7 | </ietf:e1>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:e1]</XPath>⏎ |
0 | <ietf:e2 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org"> | |
1 | <ietf:e21></ietf:e21> | |
2 | </ietf:e2>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:e2]</XPath>⏎ |
0 | <ietf:e11 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:space="true"> | |
1 | <ietf:e111></ietf:e111> | |
2 | </ietf:e11>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:e11]</XPath>⏎ |
0 | <ietf:e11 xmlns:ietf="http://www.ietf.org"> | |
1 | <ietf:e111></ietf:e111> | |
2 | </ietf:e11><ietf:e12 xmlns:ietf="http://www.ietf.org" at="2"> | |
3 | <ietf:e121></ietf:e121> | |
4 | </ietf:e12>⏎ |
0 | <ietf:e11 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" xml:space="true"> | |
1 | <ietf:e111></ietf:e111> | |
2 | </ietf:e11><ietf:e12 xmlns:ietf="http://www.ietf.org" xmlns:w3c="http://www.w3.org" at="2" xml:space="true"> | |
3 | <ietf:e121></ietf:e121> | |
4 | </ietf:e12>⏎ |
0 | <XPath xmlns:ietf="http://www.ietf.org">(//. | //@* | //namespace::*) [ancestor-or-self::ietf:e11 or ancestor-or-self::ietf:e12]</XPath>⏎ |
0 | <?xml version="1.0" encoding="UTF-8"?> | |
1 | <ietf:c14n11XmlSpaceDoc1 xmlns:ietf="http://www.ietf.org" | |
2 | xmlns:w3c="http://www.w3.org"> | |
3 | <ietf:e1 xml:space="true"> | |
4 | <ietf:e11> | |
5 | <ietf:e111 /> | |
6 | </ietf:e11> | |
7 | <ietf:e12 at="2"> | |
8 | <ietf:e121 /> | |
9 | </ietf:e12> | |
10 | </ietf:e1> | |
11 | <ietf:e2 > | |
12 | <ietf:e21 /> | |
13 | </ietf:e2> | |
14 | </ietf:c14n11XmlSpaceDoc1>⏎ |
163 | 163 | |
164 | 164 | if(INSTALL_TESTS) |
165 | 165 | install(FILES https.pl |
166 | DESTINATION ${INSTALL_TESTS_DIR}/packages/ssl) | |
166 | DESTINATION ${INSTALL_TESTS_DIR}/packages/ssl | |
167 | COMPONENT Tests) | |
167 | 168 | install(DIRECTORY etc |
168 | DESTINATION ${INSTALL_TESTS_DIR}/packages/ssl) | |
169 | DESTINATION ${INSTALL_TESTS_DIR}/packages/ssl | |
170 | COMPONENT Tests) | |
169 | 171 | install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tests |
170 | DESTINATION ${INSTALL_TESTS_DIR}/packages/ssl) | |
172 | DESTINATION ${INSTALL_TESTS_DIR}/packages/ssl | |
173 | COMPONENT Tests) | |
171 | 174 | endif() |
172 | 175 | endif() |
173 | 176 | endif(BUILD_TESTING) |
223 | 226 | install_src(pkg_ssl_etc |
224 | 227 | DIRECTORY etc |
225 | 228 | DESTINATION |
226 | ${SWIPL_INSTALL_PREFIX}/doc/packages/examples/${SWIPL_PKG}) | |
229 | ${SWIPL_INSTALL_SHARE_PREFIX}/doc/packages/examples/${SWIPL_PKG} | |
230 | COMPONENT Examples) | |
227 | 231 | |
228 | 232 | pkg_doc(ssl |
229 | 233 | SOURCES |
286 | 286 | /* |
287 | 287 | * Control function. Currently only supports flushing and detecting EOF. |
288 | 288 | * There are several more mandatory, but as-yet unsupported functions... |
289 | * | |
290 | * We should not consider a timeout to be end-of-file. If we do so, | |
291 | * OpenSSL as of 1.1.1e will propagate this as an SSL_ERROR_SSL and we | |
292 | * cannot resume the connection. Note that the TIMEOUT flag is cleared | |
293 | * by the next read operation. Also, if this flag is set, the last read | |
294 | * operation did call Sfillbuf(), and we thus do know the buffer is | |
295 | * empty. Diagnosed by Matt Lilley. | |
289 | 296 | */ |
290 | 297 | |
291 | 298 | static long |
298 | 305 | Sflush(stream); |
299 | 306 | return 1; |
300 | 307 | case BIO_CTRL_EOF: |
301 | return Sfeof(stream); | |
308 | return !(stream->flags&SIO_TIMEOUT) && Sfeof(stream); | |
302 | 309 | } |
303 | 310 | |
304 | 311 | return 0; |
Binary diff not shown
1 | 1 | Data: |
2 | 2 | Version: 3 (0x2) |
3 | 3 | Serial Number: |
4 | a6:11:83:6b:46:29:8a:72 | |
5 | Signature Algorithm: sha1WithRSAEncryption | |
4 | 9d:c0:87:97:a0:f6:3f:7c | |
5 | Signature Algorithm: sha256WithRSAEncryption | |
6 | 6 | Issuer: C=NL, ST=Noord-Holland, O=Diff Automatisering, OU=Support group, CN=J. van der Steen/emailAddress=info@diff.nl |
7 | 7 | Validity |
8 | Not Before: Jul 3 15:11:14 2008 GMT | |
9 | Not After : Nov 19 15:11:14 2035 GMT | |
10 | Subject: C=NL, ST=Noord-Holland, L=Amsterdam, O=University of Amsterdam, OU=Client, CN=Jan Wielemaker/emailAddress=wielemak@science.uva.nl | |
8 | Not Before: Apr 1 09:34:34 2020 GMT | |
9 | Not After : Apr 1 09:34:34 2021 GMT | |
10 | Subject: C=NL, ST=Noord-Holland, L=Amsterdam, O=Diff Automatisering, OU=Client, CN=J. van der Steen/emailAddress=J.van.der.Steen@diff.nl | |
11 | 11 | Subject Public Key Info: |
12 | 12 | Public Key Algorithm: rsaEncryption |
13 | RSA Public Key: (1024 bit) | |
14 | Modulus (1024 bit): | |
15 | 00:b0:f8:4b:6f:fb:04:72:e5:79:5e:07:14:45:d3: | |
16 | 9d:4f:2f:ab:ee:ba:6e:07:52:ce:34:37:b5:4b:31: | |
17 | a8:0f:02:a5:24:bb:41:37:6c:2f:17:e2:7f:fe:c0: | |
18 | 2a:84:6d:e7:3b:fb:b9:4a:df:09:ea:0d:47:2a:d0: | |
19 | fe:7b:82:12:ca:6b:5f:70:bb:a5:91:a3:d0:f9:4c: | |
20 | c7:7b:4b:8d:7f:a7:6a:f9:27:34:32:43:7b:f2:e4: | |
21 | d6:8f:d2:42:ed:21:28:1c:67:62:6e:84:75:ab:da: | |
22 | 90:a8:1e:09:70:47:c5:51:ae:d1:74:88:73:74:e7: | |
23 | 65:f3:ea:4d:e0:75:a6:64:6f | |
13 | Public-Key: (2048 bit) | |
14 | Modulus: | |
15 | 00:a4:cf:45:ac:02:9b:ba:01:48:79:50:2f:f4:58: | |
16 | 7b:e0:47:c8:0e:12:9c:f6:9f:29:71:24:e4:41:cc: | |
17 | 02:45:03:51:5f:34:69:da:b6:7d:83:29:dd:c7:d8: | |
18 | e0:05:29:9c:7e:a9:a0:31:83:53:3c:df:17:fb:12: | |
19 | da:1a:c3:6b:44:78:b3:17:9b:44:f7:8d:3e:12:5f: | |
20 | cc:31:58:a7:20:ab:d3:dd:45:c7:52:99:d2:48:8b: | |
21 | 72:85:d3:bb:04:cd:f9:e0:b7:56:ab:79:b7:66:40: | |
22 | c7:e8:7a:52:ed:ed:55:1b:db:5b:1d:9b:dd:0e:ad: | |
23 | 68:2d:c3:da:67:3c:be:6e:08:8f:a3:88:2a:d7:27: | |
24 | 0d:b6:90:f0:2d:a8:0b:54:db:95:ba:b9:0a:67:f4: | |
25 | 00:65:a0:a7:cf:81:2e:e5:6a:52:6b:18:28:74:82: | |
26 | 9f:52:14:11:96:d1:dd:23:25:74:70:81:1e:41:00: | |
27 | ec:65:3b:ac:18:30:06:f6:ed:58:d7:2c:0f:77:fa: | |
28 | 53:7c:40:02:e5:70:4a:b8:e0:b3:7b:c5:34:93:f1: | |
29 | 77:af:2f:37:a6:09:c9:e6:3d:c4:0f:15:d7:8e:6c: | |
30 | 3c:10:ab:2a:5f:38:77:b1:7d:f1:06:6d:49:1e:5a: | |
31 | 0f:26:68:fc:eb:e7:c9:b1:b7:87:4e:a6:12:de:b5: | |
32 | 5a:1b | |
24 | 33 | Exponent: 65537 (0x10001) |
25 | 34 | X509v3 extensions: |
26 | 35 | X509v3 Basic Constraints: |
28 | 37 | Netscape Comment: |
29 | 38 | OpenSSL Generated Certificate |
30 | 39 | X509v3 Subject Key Identifier: |
31 | F1:3E:D8:C4:80:01:24:70:79:03:AB:76:81:A4:4F:50:A8:F1:B2:FD | |
40 | BD:79:A2:A6:3C:EC:1A:80:75:8D:60:9B:A6:F9:02:6B:C0:ED:E4:8A | |
32 | 41 | X509v3 Authority Key Identifier: |
33 | keyid:20:1B:40:E4:00:18:7C:E6:67:7A:80:16:FE:15:07:9E:BD:77:27:26 | |
42 | keyid:E2:7B:60:8C:77:BB:B2:74:B8:FD:D6:2C:A9:D3:B9:35:97:12:87:EC | |
34 | 43 | |
35 | Signature Algorithm: sha1WithRSAEncryption | |
36 | 2d:9f:13:8b:ca:d6:0a:f0:ef:75:52:ab:a0:fe:6f:f1:14:16: | |
37 | f9:4e:f5:77:ac:55:9b:bb:31:d3:fa:e5:4f:9a:83:91:7d:c5: | |
38 | 90:b1:94:d1:1b:3b:a2:b4:fa:5f:43:79:20:ec:b2:48:61:fc: | |
39 | bf:75:25:75:64:2d:c6:02:61:4b:4a:d9:50:eb:bc:ba:e7:cb: | |
40 | 31:91:f2:18:6b:62:8f:e4:29:ea:83:29:54:53:05:40:5c:86: | |
41 | 11:d2:56:0d:4a:39:f6:b4:f0:78:86:98:15:da:3a:cd:86:7e: | |
42 | c0:bc:71:dc:7d:69:f8:0b:56:17:a3:3b:6d:e3:65:73:1d:64: | |
43 | 21:f0 | |
44 | Signature Algorithm: sha256WithRSAEncryption | |
45 | 45:62:87:35:99:a7:74:b9:de:08:7c:2f:41:f5:c8:1e:3e:df: | |
46 | c6:54:f3:e4:fa:25:a7:7b:8f:b3:1e:89:d2:83:97:50:fd:84: | |
47 | c8:53:1d:ab:9c:61:80:44:5f:72:29:6b:59:35:ab:11:45:42: | |
48 | 4f:0b:02:88:55:b9:4b:40:9a:b0:0b:ed:aa:a6:7a:44:b1:f6: | |
49 | 01:f2:3c:fd:54:d5:93:8b:9a:68:18:ed:77:c3:39:79:f5:59: | |
50 | c2:7a:7f:d0:03:b1:a5:d8:27:62:c8:33:06:7c:c5:26:32:cd: | |
51 | 92:ce:b0:2e:7f:16:e8:e3:3f:28:8e:b3:66:cd:a5:b1:64:db: | |
52 | 33:0f:c6:12:f3:22:66:0f:6f:b2:1c:fb:81:bb:a4:ad:c8:27: | |
53 | 9f:62:72:44:9b:b7:da:3c:10:0e:95:87:33:91:59:a3:0c:ca: | |
54 | d9:15:f0:de:52:25:f9:14:16:da:69:d8:af:00:87:f8:f1:6f: | |
55 | 26:07:9a:f7:4e:ad:07:23:ef:e2:aa:94:b2:45:2a:f7:55:65: | |
56 | e4:59:ee:1c:5d:69:64:4f:b3:2f:a7:54:03:36:05:10:8a:43: | |
57 | 3c:ce:8c:97:91:b6:17:4b:85:ab:a9:51:8f:de:1a:89:4b:1e: | |
58 | 5f:39:47:b3:ab:cc:14:f4:c6:ba:d3:4a:6f:6a:fe:aa:2d:2c: | |
59 | 81:53:9a:53 | |
44 | 60 | -----BEGIN CERTIFICATE----- |
45 | MIIDOzCCAqSgAwIBAgIJAKYRg2tGKYpyMA0GCSqGSIb3DQEBBQUAMIGTMQswCQYD | |
46 | VQQGEwJOTDEWMBQGA1UECBMNTm9vcmQtSG9sbGFuZDEcMBoGA1UEChMTRGlmZiBB | |
47 | dXRvbWF0aXNlcmluZzEWMBQGA1UECxMNU3VwcG9ydCBncm91cDEZMBcGA1UEAxMQ | |
61 | MIIEPjCCAyagAwIBAgIJAJ3Ah5eg9j98MA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD | |
62 | VQQGEwJOTDEWMBQGA1UECAwNTm9vcmQtSG9sbGFuZDEcMBoGA1UECgwTRGlmZiBB | |
63 | dXRvbWF0aXNlcmluZzEWMBQGA1UECwwNU3VwcG9ydCBncm91cDEZMBcGA1UEAwwQ | |
48 | 64 | Si4gdmFuIGRlciBTdGVlbjEbMBkGCSqGSIb3DQEJARYMaW5mb0BkaWZmLm5sMB4X |
49 | DTA4MDcwMzE1MTExNFoXDTM1MTExOTE1MTExNFowga0xCzAJBgNVBAYTAk5MMRYw | |
50 | FAYDVQQIEw1Ob29yZC1Ib2xsYW5kMRIwEAYDVQQHEwlBbXN0ZXJkYW0xIDAeBgNV | |
51 | BAoTF1VuaXZlcnNpdHkgb2YgQW1zdGVyZGFtMQ8wDQYDVQQLEwZDbGllbnQxFzAV | |
52 | BgNVBAMTDkphbiBXaWVsZW1ha2VyMSYwJAYJKoZIhvcNAQkBFhd3aWVsZW1ha0Bz | |
53 | Y2llbmNlLnV2YS5ubDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsPhLb/sE | |
54 | cuV5XgcURdOdTy+r7rpuB1LONDe1SzGoDwKlJLtBN2wvF+J//sAqhG3nO/u5St8J | |
55 | 6g1HKtD+e4ISymtfcLulkaPQ+UzHe0uNf6dq+Sc0MkN78uTWj9JC7SEoHGdiboR1 | |
56 | q9qQqB4JcEfFUa7RdIhzdOdl8+pN4HWmZG8CAwEAAaN7MHkwCQYDVR0TBAIwADAs | |
57 | BglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYD | |
58 | VR0OBBYEFPE+2MSAASRweQOrdoGkT1Co8bL9MB8GA1UdIwQYMBaAFCAbQOQAGHzm | |
59 | Z3qAFv4VB569dycmMA0GCSqGSIb3DQEBBQUAA4GBAC2fE4vK1grw73VSq6D+b/EU | |
60 | FvlO9XesVZu7MdP65U+ag5F9xZCxlNEbO6K0+l9DeSDsskhh/L91JXVkLcYCYUtK | |
61 | 2VDrvLrnyzGR8hhrYo/kKeqDKVRTBUBchhHSVg1KOfa08HiGmBXaOs2GfsC8cdx9 | |
62 | afgLVhejO23jZXMdZCHw | |
65 | DTIwMDQwMTA5MzQzNFoXDTIxMDQwMTA5MzQzNFowgasxCzAJBgNVBAYTAk5MMRYw | |
66 | FAYDVQQIDA1Ob29yZC1Ib2xsYW5kMRIwEAYDVQQHDAlBbXN0ZXJkYW0xHDAaBgNV | |
67 | BAoME0RpZmYgQXV0b21hdGlzZXJpbmcxDzANBgNVBAsMBkNsaWVudDEZMBcGA1UE | |
68 | AwwQSi4gdmFuIGRlciBTdGVlbjEmMCQGCSqGSIb3DQEJARYXSi52YW4uZGVyLlN0 | |
69 | ZWVuQGRpZmYubmwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCkz0Ws | |
70 | Apu6AUh5UC/0WHvgR8gOEpz2nylxJORBzAJFA1FfNGnatn2DKd3H2OAFKZx+qaAx | |
71 | g1M83xf7Etoaw2tEeLMXm0T3jT4SX8wxWKcgq9PdRcdSmdJIi3KF07sEzfngt1ar | |
72 | ebdmQMfoelLt7VUb21sdm90OrWgtw9pnPL5uCI+jiCrXJw22kPAtqAtU25W6uQpn | |
73 | 9ABloKfPgS7lalJrGCh0gp9SFBGW0d0jJXRwgR5BAOxlO6wYMAb27VjXLA93+lN8 | |
74 | QALlcEq44LN7xTST8XevLzemCcnmPcQPFdeObDwQqypfOHexffEGbUkeWg8maPzr | |
75 | 58mxt4dOphLetVobAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8W | |
76 | HU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBS9eaKmPOwa | |
77 | gHWNYJum+QJrwO3kijAfBgNVHSMEGDAWgBTie2CMd7uydLj91iyp07k1lxKH7DAN | |
78 | BgkqhkiG9w0BAQsFAAOCAQEARWKHNZmndLneCHwvQfXIHj7fxlTz5Polp3uPsx6J | |
79 | 0oOXUP2EyFMdq5xhgERfcilrWTWrEUVCTwsCiFW5S0CasAvtqqZ6RLH2AfI8/VTV | |
80 | k4uaaBjtd8M5efVZwnp/0AOxpdgnYsgzBnzFJjLNks6wLn8W6OM/KI6zZs2lsWTb | |
81 | Mw/GEvMiZg9vshz7gbukrcgnn2JyRJu32jwQDpWHM5FZowzK2RXw3lIl+RQW2mnY | |
82 | rwCH+PFvJgea906tByPv4qqUskUq91Vl5FnuHF1pZE+zL6dUAzYFEIpDPM6Ml5G2 | |
83 | F0uFq6lRj94aiUseXzlHs6vMFPTGutNKb2r+qi0sgVOaUw== | |
63 | 84 | -----END CERTIFICATE----- |
0 | -----BEGIN RSA PRIVATE KEY----- | |
1 | Proc-Type: 4,ENCRYPTED | |
2 | DEK-Info: DES-EDE3-CBC,2A0D4B5A7F746951 | |
3 | ||
4 | PVt0XRMXqvvZpSyfsPlDjXlemkSeqA4hGSq+FXyCE2vY7jF6nG8OEyFLzBQK1QHb | |
5 | /rGNrX81s3vwuqAhtikM8CtBbLCyKXKzv5gka6f0FoD2TfcLZxQyO98AK7mY70/i | |
6 | gPYN+8hsl/riEtdTrMIbD/4hVGivgVS592iFpfFyjuv/utgJF/gEqMS3J7IPwF7q | |
7 | NvqWHQ0N1RBQdHv0zLjqpi582h/XagqOGzO0ShtesSgDw6WDxAztJXGzjb8aOA2a | |
8 | EvU6zdhKYVdvwGySIEJ0CVE8Mawmp1rBIPNGSl6MPP8lb4zGSsX6kraAb9ZFaZqr | |
9 | TjZv438VlzMILtSOzHguT49gpjkqSf/3erQ9GLo+CYGZToQXbyUSKhTCxO37sQxU | |
10 | +tWZfXyDp8s5NJV5G3y+wrPFq4TKkPe+F11cerX/IsIefUaLCDMWCohVY2g05e9H | |
11 | puWkGxj8Ry/ca1Y7IPmSj/tqtH36I1beio9m0tMSc/cZM9AYAS/gvUUGCTvSUouV | |
12 | HO5lTrTc0frRF9fbMDLrlziS6IZbyJEN32irEiSF2UkQRsf3O3mdmV/UJ2U55gLy | |
13 | /lbe+qD0imjMZOk+pFmPm3ZrZR7hEbvG5k/P58mdoqAKRbq19MU1fATM8DlkJaHi | |
14 | 38MJMlEfnME5l7bAa1FRAf/j89/H+NgnDsDlhC5DeNzAMW6RbaA9oG3MaA6OBBlg | |
15 | jHxJgjk95VlJrWquBdSxVhknEE2sHOm8+ulhRPxzgYJkxAWeZU9yrOwtEl4JU+s+ | |
16 | lLS/IXF4ba499oPjd5CKSmqBQL6KWb1o8Pay8zD8MX+MmPM9tZY+MA== | |
17 | -----END RSA PRIVATE KEY----- | |
18 | -----BEGIN CERTIFICATE REQUEST----- | |
19 | MIICLjCCAZcCAQAwga0xCzAJBgNVBAYTAk5MMRYwFAYDVQQIEw1Ob29yZC1Ib2xs | |
20 | YW5kMRIwEAYDVQQHEwlBbXN0ZXJkYW0xIDAeBgNVBAoTF1VuaXZlcnNpdHkgb2Yg | |
21 | QW1zdGVyZGFtMQ8wDQYDVQQLEwZDbGllbnQxFzAVBgNVBAMTDkphbiBXaWVsZW1h | |
22 | a2VyMSYwJAYJKoZIhvcNAQkBFhd3aWVsZW1ha0BzY2llbmNlLnV2YS5ubDCBnzAN | |
23 | BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsPhLb/sEcuV5XgcURdOdTy+r7rpuB1LO | |
24 | NDe1SzGoDwKlJLtBN2wvF+J//sAqhG3nO/u5St8J6g1HKtD+e4ISymtfcLulkaPQ | |
25 | +UzHe0uNf6dq+Sc0MkN78uTWj9JC7SEoHGdiboR1q9qQqB4JcEfFUa7RdIhzdOdl | |
26 | 8+pN4HWmZG8CAwEAAaBAMBUGCSqGSIb3DQEJBzEIEwZhYXBqZXMwJwYJKoZIhvcN | |
27 | AQkCMRoTGDpVbml2ZXJzaXR5IG9mIEFtc3RlcmRhbTANBgkqhkiG9w0BAQQFAAOB | |
28 | gQAiPUUThFT51aUzGnSW3A5XR7bsExSptWWtVO/hQOiReEKRYUuf1mKCaSQz+Nt5 | |
29 | n3VZRV3w01yhnv4WVQwYRAdwkBP0Cuc1oXmatY7Tc93SiKO6yEvUhdlQxeeCih/Q | |
30 | axIQqWm+/Rwh42XxJuVR+jOEr5m/bZuCOHJfAe9clLMpmQ== | |
31 | -----END CERTIFICATE REQUEST----- | |
0 | -----BEGIN ENCRYPTED PRIVATE KEY----- | |
1 | MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQInpQwcijL1RYCAggA | |
2 | MBQGCCqGSIb3DQMHBAhIc52+Uha4wQSCBMjmMOwEzC6itEG8h4rBZyvXve8m5aOe | |
3 | LUjpdHShjAYrOeCcX9bRIrwczW7+y2zDYlWd9b6a22/Yijc35O5cPyzeoxHgv9bY | |
4 | ChaZN0xnqo/4g+c7vSGi+hMnT1wzBsfyJ3GawWbDL7C4Zto1V92gxxZSQM8NqXDH | |
5 | 9SrOY+RMvD6mBk1s94g+LSPtDlcTvNEN7aBvVZGLVgREtsDT5p1AMZivrzTZO2Z0 | |
6 | V2N8D92zeLxwiAmN+ymgNgMrwZ5jy9b6X7vvdVgqpmohNugi4oK1llfSP7V77MMG | |
7 | uLCZzJHQlb/aZwWR7XH+GtBpGChyo2MCErdGvBtHTgwzbHUGZuaVZNISuN+xH8bY | |
8 | s9e3D20qU0+m4hoEKowtydCEj5+MBtIQVpp2Kasa68b+HEJbecyhOf0Rrkn83G43 | |
9 | n8h49mH7ltjkCqcaXPjQ7O1l0TiqqrUvSvuzU4Bh51PimzpEme/Y0NJ0nQy5pCxP | |
10 | bh7mArQyr4F68TXOB5Pxp5JmH3x7FpBjFTXu/shOE828Xq97c1o0fsNiH0xmgJQE | |
11 | PBrSqUPL+4ezjHbP11MMx28e6wOIUtvXThnkyvP9xp0/p4U+Jm8Otw2YDJ5AFmey | |
12 | rLPy/yvEbQ+Y6jnwetsSDBkZYWGoWy2dWSOjzT8KpWg7ozYFKJ6fO72I6tELRIWr | |
13 | 83db6o+DlgSxiMyoRmOjkQ+2nBA6CYe59DUQQnYcnbmWJBlnxgeAqx22oq0MxAhE | |
14 | D+N9cxVAbko6f7Izz4on1RcvKGfRVjGuYzuONXUdtVTN0LgHTq6s1fvf/VOsq/nW | |
15 | SzNjA5slC/19EypbC7aoGSdBDBBG5mGd8O1yZ/L6nDGsi8za5DAhxDayXoQSrs+Z | |
16 | OIdtdZ7pEog3I/X6N0X9VeAcCmuvrQYbOrNoX9ryKJeMM0TRUjAJyezyx0QOap9A | |
17 | iPiNTUZz6zyGKxLRmN2VoRlZkjs55/Jod/zhy/5tMhOfHTRW75ve5dRVMxlTeoXm | |
18 | BtzpVWqOa4r38HrXnwgSA4Z1mTJputg5biZgGIiUwrc3DdorGWR3vbKTSVJdB9ZD | |
19 | 26GzEBLrsOnB0Yc1ZjZWKs8+xlXqfAV3Z0IMVheZqx8tbxG1Z4LUIIKq51BGdFNx | |
20 | 6+gKTnPhZJoQePD5TI9vDklY7QGe/vpvllC0Wi0NtgCn/vgUlc1ljXY8aT2hRE3W | |
21 | KrQFB7ekPSodtBpARu8skgfgERKAYEnSJgdt2Y9soUw9h0Teyinecptl51DgFXPn | |
22 | 9c1vqlEbtkKqcQJiPcfvLKwgbzArIDdSK25Vz81ctZh1d3Qu2NrfO/JjXFPAA1hh | |
23 | 5A6AoZqHWB2150pDMOLSMH/XgcFi7AV5RWT8D/pEIChNlExKLUNc6VpU1nAmCbWw | |
24 | 8VxuLO/wFV9nSgQJUM4Hzgu8jeyR+ZCMH0A9VENztoOFKhgFezRfn73bCipMKlGa | |
25 | EE5QbPo/+O2k9mcNHAv+/ZgN1RBekjnWkVd2WoLjtOrzDzASaMzK381a/x9qQ+6P | |
26 | cwcKkRGCaCopjUA5Ddki9dSSY+IosojuM/sH+NGNfnN6/M6z5MNqURbEpLXYeZDx | |
27 | CLgos3Y1dV2BKZwvaWWsqw5aCTjcM0HPs/d52FMMo2u/qLYPvVRbBR7USokY+Izd | |
28 | Tds= | |
29 | -----END ENCRYPTED PRIVATE KEY----- |
1 | 1 | Data: |
2 | 2 | Version: 3 (0x2) |
3 | 3 | Serial Number: |
4 | ea:f9:b5:1b:4a:64:0b:4e | |
5 | Signature Algorithm: sha1WithRSAEncryption | |
4 | 9d:c0:87:97:a0:f6:3f:7b | |
5 | Signature Algorithm: sha256WithRSAEncryption | |
6 | 6 | Issuer: C=NL, ST=Noord-Holland, O=Diff Automatisering, OU=Support group, CN=J. van der Steen/emailAddress=info@diff.nl |
7 | 7 | Validity |
8 | Not Before: Feb 27 21:51:56 2010 GMT | |
9 | Not After : Jul 15 21:51:56 2037 GMT | |
8 | Not Before: Apr 1 09:32:06 2020 GMT | |
9 | Not After : Apr 1 09:32:06 2023 GMT | |
10 | 10 | Subject: C=NL, ST=Noord-Holland, O=Diff Automatisering, OU=Support group, CN=J. van der Steen/emailAddress=info@diff.nl |
11 | 11 | Subject Public Key Info: |
12 | 12 | Public Key Algorithm: rsaEncryption |
13 | RSA Public Key: (1024 bit) | |
14 | Modulus (1024 bit): | |
15 | 00:a3:89:65:d6:f6:34:38:be:8d:bf:0c:7b:95:0e: | |
16 | 01:0a:6e:3f:d6:54:c4:c4:d9:65:db:48:14:be:98: | |
17 | 79:e0:bc:f8:be:76:57:d3:91:f9:15:16:12:53:24: | |
18 | ec:12:15:71:bd:c6:96:bc:cf:5c:5f:d0:1e:2d:f4: | |
19 | 79:ab:81:aa:29:76:a5:14:bb:0c:84:bd:93:84:43: | |
20 | 0b:51:ef:f4:64:8c:14:cc:6e:f2:f5:b5:cd:d7:66: | |
21 | 72:6b:96:e6:4f:e4:66:53:f0:95:7e:de:c5:8d:af: | |
22 | ba:3b:83:43:7a:80:4b:b7:a0:47:c1:75:6e:97:3f: | |
23 | ca:a0:bb:50:a3:a9:f3:7b:bf | |
13 | Public-Key: (2048 bit) | |
14 | Modulus: | |
15 | 00:d1:37:67:ad:b9:9f:0c:a7:93:cf:20:bf:1d:c0: | |
16 | a8:ba:5c:ad:c6:ff:48:68:a0:93:9e:89:a7:1c:4e: | |
17 | ff:88:07:2d:45:59:e1:a5:ae:2f:71:b1:30:b9:d1: | |
18 | 95:2b:a8:46:69:62:f2:25:8e:d4:15:e0:f5:2f:68: | |
19 | 26:21:f7:8e:7a:83:81:63:4e:63:0c:a5:3f:20:c7: | |
20 | 60:37:9f:c6:d8:e8:c7:95:6f:85:23:b9:4d:df:a3: | |
21 | 1d:2e:94:02:9a:14:db:28:c7:c3:0e:41:d5:68:7a: | |
22 | 82:11:98:8d:fc:ef:2f:8b:85:70:33:fa:26:ff:d4: | |
23 | 88:73:11:22:dc:0e:28:49:0b:5a:74:a3:a0:9a:44: | |
24 | e8:0c:2d:47:42:29:c1:cc:d9:77:04:4f:42:f5:a3: | |
25 | 87:19:4c:72:b2:9e:9d:f0:3b:58:2e:18:cf:2d:4d: | |
26 | e2:b5:c2:00:9e:67:11:0c:78:bb:53:43:16:55:b1: | |
27 | c6:f6:8a:ea:43:6d:2b:59:48:da:21:d7:32:84:d9: | |
28 | f5:d6:1c:af:03:f7:4a:b7:d3:db:24:f4:85:24:9b: | |
29 | de:17:e5:b8:58:f4:a2:2c:eb:86:59:3b:ac:1e:13: | |
30 | 8c:a3:7c:5d:eb:42:db:1b:5b:8d:86:4c:2f:ad:b0: | |
31 | 1a:65:32:5f:fd:ad:cb:13:a6:ff:fe:e2:d6:5e:1b: | |
32 | f0:a1 | |
24 | 33 | Exponent: 65537 (0x10001) |
25 | 34 | X509v3 extensions: |
26 | 35 | X509v3 Subject Key Identifier: |
27 | 20:1B:40:E4:00:18:7C:E6:67:7A:80:16:FE:15:07:9E:BD:77:27:26 | |
36 | E2:7B:60:8C:77:BB:B2:74:B8:FD:D6:2C:A9:D3:B9:35:97:12:87:EC | |
28 | 37 | X509v3 Authority Key Identifier: |
29 | keyid:20:1B:40:E4:00:18:7C:E6:67:7A:80:16:FE:15:07:9E:BD:77:27:26 | |
30 | DirName:/C=NL/ST=Noord-Holland/O=Diff Automatisering/OU=Support group/CN=J. van der Steen/emailAddress=info@diff.nl | |
31 | serial:EA:F9:B5:1B:4A:64:0B:4E | |
38 | keyid:E2:7B:60:8C:77:BB:B2:74:B8:FD:D6:2C:A9:D3:B9:35:97:12:87:EC | |
32 | 39 | |
33 | 40 | X509v3 Basic Constraints: |
34 | 41 | CA:TRUE |
35 | Signature Algorithm: sha1WithRSAEncryption | |
36 | 8e:06:3b:75:99:ac:d4:da:04:e7:b7:fa:46:27:82:56:06:39: | |
37 | dd:5c:04:ab:24:7f:a6:48:84:51:83:ca:8e:75:6f:dd:91:bc: | |
38 | ca:30:7a:25:18:d2:dd:84:71:f2:ed:ea:21:fe:99:19:be:0b: | |
39 | 82:0a:8b:7c:2e:c1:ad:f0:6a:5c:f0:c4:85:2a:f6:23:30:78: | |
40 | 1d:e4:83:c5:4a:e4:be:3f:b5:3b:e7:c3:82:53:39:98:9b:ca: | |
41 | 45:e1:4c:4b:7f:9c:3d:73:93:46:75:50:17:fc:52:53:43:7c: | |
42 | a1:30:b2:72:c0:d1:d6:c0:26:0b:a9:04:a7:d2:4f:f7:f6:bd: | |
43 | 0c:a3 | |
42 | Signature Algorithm: sha256WithRSAEncryption | |
43 | 2a:0f:94:6c:75:27:e1:f4:0a:6a:a0:0e:0e:f1:c9:ef:b2:83: | |
44 | ae:56:d9:6e:e2:e2:69:ea:a4:2d:ad:fd:79:57:64:00:0c:bd: | |
45 | c8:d3:65:2d:d8:4d:5a:e5:b2:14:21:9c:d5:64:1b:ed:86:0d: | |
46 | c4:92:28:c5:14:b4:c2:8c:72:fa:4a:97:4f:2d:e9:35:80:5a: | |
47 | e4:ad:2d:f3:61:4b:c7:b0:bc:6d:42:e2:07:50:88:5c:42:bf: | |
48 | 3b:ac:65:25:b4:6a:ef:e2:cd:30:6b:1e:59:10:97:27:dd:10: | |
49 | 61:3e:e1:2f:c0:fd:5a:53:c1:6f:bb:54:94:90:fb:a0:d9:6b: | |
50 | 2e:6e:77:79:d6:52:ba:04:70:9d:1e:72:d6:62:a6:e2:c6:60: | |
51 | 1f:2e:99:e0:62:97:41:b4:f8:a3:5e:a4:78:80:ee:51:b8:4a: | |
52 | 7c:07:a0:6d:c5:a2:0d:c7:91:d1:7b:3c:84:ee:41:c7:60:e5: | |
53 | 7f:52:f9:ef:1c:d3:98:35:8c:da:f7:e0:78:1f:13:0d:ea:64: | |
54 | d2:38:a5:47:71:32:65:63:7a:7e:d1:de:73:18:b3:73:ed:d3: | |
55 | f1:0c:f7:56:f5:1e:2b:a6:5d:9b:ac:9a:27:52:fe:ea:51:2a: | |
56 | ef:76:55:d3:31:20:87:e4:5f:f4:dc:50:66:49:02:53:ac:ff: | |
57 | fb:35:ac:21 | |
44 | 58 | -----BEGIN CERTIFICATE----- |
45 | MIIDojCCAwugAwIBAgIJAOr5tRtKZAtOMA0GCSqGSIb3DQEBBQUAMIGTMQswCQYD | |
46 | VQQGEwJOTDEWMBQGA1UECBMNTm9vcmQtSG9sbGFuZDEcMBoGA1UEChMTRGlmZiBB | |
47 | dXRvbWF0aXNlcmluZzEWMBQGA1UECxMNU3VwcG9ydCBncm91cDEZMBcGA1UEAxMQ | |
59 | MIID+zCCAuOgAwIBAgIJAJ3Ah5eg9j97MA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD | |
60 | VQQGEwJOTDEWMBQGA1UECAwNTm9vcmQtSG9sbGFuZDEcMBoGA1UECgwTRGlmZiBB | |
61 | dXRvbWF0aXNlcmluZzEWMBQGA1UECwwNU3VwcG9ydCBncm91cDEZMBcGA1UEAwwQ | |
48 | 62 | Si4gdmFuIGRlciBTdGVlbjEbMBkGCSqGSIb3DQEJARYMaW5mb0BkaWZmLm5sMB4X |
49 | DTEwMDIyNzIxNTE1NloXDTM3MDcxNTIxNTE1NlowgZMxCzAJBgNVBAYTAk5MMRYw | |
50 | FAYDVQQIEw1Ob29yZC1Ib2xsYW5kMRwwGgYDVQQKExNEaWZmIEF1dG9tYXRpc2Vy | |
51 | aW5nMRYwFAYDVQQLEw1TdXBwb3J0IGdyb3VwMRkwFwYDVQQDExBKLiB2YW4gZGVy | |
52 | IFN0ZWVuMRswGQYJKoZIhvcNAQkBFgxpbmZvQGRpZmYubmwwgZ8wDQYJKoZIhvcN | |
53 | AQEBBQADgY0AMIGJAoGBAKOJZdb2NDi+jb8Me5UOAQpuP9ZUxMTZZdtIFL6YeeC8 | |
54 | +L52V9OR+RUWElMk7BIVcb3GlrzPXF/QHi30eauBqil2pRS7DIS9k4RDC1Hv9GSM | |
55 | FMxu8vW1zddmcmuW5k/kZlPwlX7exY2vujuDQ3qAS7egR8F1bpc/yqC7UKOp83u/ | |
56 | AgMBAAGjgfswgfgwHQYDVR0OBBYEFCAbQOQAGHzmZ3qAFv4VB569dycmMIHIBgNV | |
57 | HSMEgcAwgb2AFCAbQOQAGHzmZ3qAFv4VB569dycmoYGZpIGWMIGTMQswCQYDVQQG | |
58 | EwJOTDEWMBQGA1UECBMNTm9vcmQtSG9sbGFuZDEcMBoGA1UEChMTRGlmZiBBdXRv | |
59 | bWF0aXNlcmluZzEWMBQGA1UECxMNU3VwcG9ydCBncm91cDEZMBcGA1UEAxMQSi4g | |
60 | dmFuIGRlciBTdGVlbjEbMBkGCSqGSIb3DQEJARYMaW5mb0BkaWZmLm5sggkA6vm1 | |
61 | G0pkC04wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCOBjt1mazU2gTn | |
62 | t/pGJ4JWBjndXASrJH+mSIRRg8qOdW/dkbzKMHolGNLdhHHy7eoh/pkZvguCCot8 | |
63 | LsGt8Gpc8MSFKvYjMHgd5IPFSuS+P7U758OCUzmYm8pF4UxLf5w9c5NGdVAX/FJT | |
64 | Q3yhMLJywNHWwCYLqQSn0k/39r0Mow== | |
63 | DTIwMDQwMTA5MzIwNloXDTIzMDQwMTA5MzIwNlowgZMxCzAJBgNVBAYTAk5MMRYw | |
64 | FAYDVQQIDA1Ob29yZC1Ib2xsYW5kMRwwGgYDVQQKDBNEaWZmIEF1dG9tYXRpc2Vy | |
65 | aW5nMRYwFAYDVQQLDA1TdXBwb3J0IGdyb3VwMRkwFwYDVQQDDBBKLiB2YW4gZGVy | |
66 | IFN0ZWVuMRswGQYJKoZIhvcNAQkBFgxpbmZvQGRpZmYubmwwggEiMA0GCSqGSIb3 | |
67 | DQEBAQUAA4IBDwAwggEKAoIBAQDRN2etuZ8Mp5PPIL8dwKi6XK3G/0hooJOeiacc | |
68 | Tv+IBy1FWeGlri9xsTC50ZUrqEZpYvIljtQV4PUvaCYh9456g4FjTmMMpT8gx2A3 | |
69 | n8bY6MeVb4UjuU3fox0ulAKaFNsox8MOQdVoeoIRmI387y+LhXAz+ib/1IhzESLc | |
70 | DihJC1p0o6CaROgMLUdCKcHM2XcET0L1o4cZTHKynp3wO1guGM8tTeK1wgCeZxEM | |
71 | eLtTQxZVscb2iupDbStZSNoh1zKE2fXWHK8D90q309sk9IUkm94X5bhY9KIs64ZZ | |
72 | O6weE4yjfF3rQtsbW42GTC+tsBplMl/9rcsTpv/+4tZeG/ChAgMBAAGjUDBOMB0G | |
73 | A1UdDgQWBBTie2CMd7uydLj91iyp07k1lxKH7DAfBgNVHSMEGDAWgBTie2CMd7uy | |
74 | dLj91iyp07k1lxKH7DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAq | |
75 | D5RsdSfh9ApqoA4O8cnvsoOuVtlu4uJp6qQtrf15V2QADL3I02Ut2E1a5bIUIZzV | |
76 | ZBvthg3EkijFFLTCjHL6SpdPLek1gFrkrS3zYUvHsLxtQuIHUIhcQr87rGUltGrv | |
77 | 4s0wax5ZEJcn3RBhPuEvwP1aU8Fvu1SUkPug2Wsubnd51lK6BHCdHnLWYqbixmAf | |
78 | LpngYpdBtPijXqR4gO5RuEp8B6BtxaINx5HRezyE7kHHYOV/UvnvHNOYNYza9+B4 | |
79 | HxMN6mTSOKVHcTJlY3p+0d5zGLNz7dPxDPdW9R4rpl2brJonUv7qUSrvdlXTMSCH | |
80 | 5F/03FBmSQJTrP/7Nawh | |
65 | 81 | -----END CERTIFICATE----- |
0 | 0 | -----BEGIN CERTIFICATE REQUEST----- |
1 | MIIB6DCCAVECAQAwgacxCzAJBgNVBAYTAk5MMRYwFAYDVQQIEw1Ob29yZC1Ib2xs | |
2 | YW5kMRIwEAYDVQQHEwlBbXN0ZXJkYW0xHDAaBgNVBAoTE0RpZmYgQXV0b21hdGlz | |
3 | ZXJpbmcxFjAUBgNVBAsTDVN1cHBvcnQgZ3JvdXAxGTAXBgNVBAMTEEouIHZhbiBk | |
4 | ZXIgU3RlZW4xGzAZBgkqhkiG9w0BCQEWDGluZm9AZGlmZi5ubDCBnzANBgkqhkiG | |
5 | 9w0BAQEFAAOBjQAwgYkCgYEAo4ll1vY0OL6Nvwx7lQ4BCm4/1lTExNll20gUvph5 | |
6 | 4Lz4vnZX05H5FRYSUyTsEhVxvcaWvM9cX9AeLfR5q4GqKXalFLsMhL2ThEMLUe/0 | |
7 | ZIwUzG7y9bXN12Zya5bmT+RmU/CVft7Fja+6O4NDeoBLt6BHwXVulz/KoLtQo6nz | |
8 | e78CAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4GBABKUDD8OpX4aB9xLS3PIkyZybMHl | |
9 | Q4IqHBYruyKEIjGqn+Sijo5yq2AAgPpiM4wyGTpAj1HamykdiI6OZO7lVYnbWy5z | |
10 | GC9aEhcNRcVU/I4CaZUx900kJT8APekdUqJXZs1+/IxAYN5+8kqElbQu6fv8Y038 | |
11 | 5xu4UNWN+2jYZGqf | |
1 | MIIC7TCCAdUCAQAwgacxCzAJBgNVBAYTAk5MMRYwFAYDVQQIDA1Ob29yZC1Ib2xs | |
2 | YW5kMRIwEAYDVQQHDAlBbXN0ZXJkYW0xHDAaBgNVBAoME0RpZmYgQXV0b21hdGlz | |
3 | ZXJpbmcxFjAUBgNVBAsMDVN1cHBvcnQgZ3JvdXAxGTAXBgNVBAMMEEouIHZhbiBk | |
4 | ZXIgU3RlZW4xGzAZBgkqhkiG9w0BCQEWDGluZm9AZGlmZi5ubDCCASIwDQYJKoZI | |
5 | hvcNAQEBBQADggEPADCCAQoCggEBANE3Z625nwynk88gvx3AqLpcrcb/SGigk56J | |
6 | pxxO/4gHLUVZ4aWuL3GxMLnRlSuoRmli8iWO1BXg9S9oJiH3jnqDgWNOYwylPyDH | |
7 | YDefxtjox5VvhSO5Td+jHS6UApoU2yjHww5B1Wh6ghGYjfzvL4uFcDP6Jv/UiHMR | |
8 | ItwOKEkLWnSjoJpE6AwtR0IpwczZdwRPQvWjhxlMcrKenfA7WC4Yzy1N4rXCAJ5n | |
9 | EQx4u1NDFlWxxvaK6kNtK1lI2iHXMoTZ9dYcrwP3SrfT2yT0hSSb3hfluFj0oizr | |
10 | hlk7rB4TjKN8XetC2xtbjYZML62wGmUyX/2tyxOm//7i1l4b8KECAwEAAaAAMA0G | |
11 | CSqGSIb3DQEBCwUAA4IBAQCKVJwFCm9LeY9onvksGuku2UhioOQAjqhMuzjOedLP | |
12 | tdsaBwFCVbvxKu/TGIwkmK2PWvKJvbn+GlXhlQlPsYDPrIeUf/9xl0hD4L9LQ0Aw | |
13 | J+e4025Tb9kLajXAnpwqFk+Z7KbGc3TbFvUCr7lLJsygdYQE+OtlBlaxrOmidIn6 | |
14 | s2GHON9nRDkeoTD6coCuMTgBWBB6ZSHCcgFy7gKNT4U3/+hYuBkg3FDZfVbXuuwn | |
15 | rveqzFfuBXlnHmJVIjqa6oXtBG/7Jm0JDOSQS2vskp3/jQAx3V4u0M77taMSC4C9 | |
16 | +pBoiH94n8fG87LbE6EQyit4KhLAluWf0jrx7vCIKGSD | |
12 | 17 | -----END CERTIFICATE REQUEST----- |
0 | 01 |
0 | V 080226140317Z A611836B46298A6F unknown /C=NL/ST=Noord-Holland/L=Amsterdam/O=Diff Automatisering/OU=Server/CN=J. van der Steen/emailAddress=J.van.der.Steen@diff.nl | |
1 | V 080226140535Z A611836B46298A70 unknown /C=NL/ST=Noord-Holland/L=Amsterdam/O=Diff Automatisering/OU=Client/CN=J. van der Steen/emailAddress=J.van.der.Steen@diff.nl | |
2 | V 351119151103Z A611836B46298A71 unknown /C=NL/ST=Noord-Holland/L=Amsterdam/O=University of Amsterdam/OU=Server/CN=Jan Wielemaker/emailAddress=wielemak@science.uva.nl | |
3 | V 351119151114Z A611836B46298A72 unknown /C=NL/ST=Noord-Holland/L=Amsterdam/O=University of Amsterdam/OU=Client/CN=Jan Wielemaker/emailAddress=wielemak@science.uva.nl | |
0 | V 230401093206Z 9DC08797A0F63F7B unknown /C=NL/ST=Noord-Holland/O=Diff Automatisering/OU=Support group/CN=J. van der Steen/emailAddress=info@diff.nl | |
1 | V 210401093434Z 9DC08797A0F63F7C unknown /C=NL/ST=Noord-Holland/L=Amsterdam/O=Diff Automatisering/OU=Client/CN=J. van der Steen/emailAddress=J.van.der.Steen@diff.nl | |
2 | V 210401093537Z 9DC08797A0F63F7D unknown /C=NL/ST=Noord-Holland/L=Amsterdam/O=Diff Automatisering/OU=Server/CN=J. van der Steen/emailAddress=J.van.der.Steen@diff.nl |
0 | Certificate: | |
1 | Data: | |
2 | Version: 3 (0x2) | |
3 | Serial Number: | |
4 | 9d:c0:87:97:a0:f6:3f:7c | |
5 | Signature Algorithm: sha256WithRSAEncryption | |
6 | Issuer: C=NL, ST=Noord-Holland, O=Diff Automatisering, OU=Support group, CN=J. van der Steen/emailAddress=info@diff.nl | |
7 | Validity | |
8 | Not Before: Apr 1 09:34:34 2020 GMT | |
9 | Not After : Apr 1 09:34:34 2021 GMT | |
10 | Subject: C=NL, ST=Noord-Holland, L=Amsterdam, O=Diff Automatisering, OU=Client, CN=J. van der Steen/emailAddress=J.van.der.Steen@diff.nl | |
11 | Subject Public Key Info: | |
12 | Public Key Algorithm: rsaEncryption | |
13 | Public-Key: (2048 bit) | |
14 | Modulus: | |
15 | 00:a4:cf:45:ac:02:9b:ba:01:48:79:50:2f:f4:58: | |
16 | 7b:e0:47:c8:0e:12:9c:f6:9f:29:71:24:e4:41:cc: | |
17 | 02:45:03:51:5f:34:69:da:b6:7d:83:29:dd:c7:d8: | |
18 | e0:05:29:9c:7e:a9:a0:31:83:53:3c:df:17:fb:12: | |
19 | da:1a:c3:6b:44:78:b3:17:9b:44:f7:8d:3e:12:5f: | |
20 | cc:31:58:a7:20:ab:d3:dd:45:c7:52:99:d2:48:8b: | |
21 | 72:85:d3:bb:04:cd:f9:e0:b7:56:ab:79:b7:66:40: | |
22 | c7:e8:7a:52:ed:ed:55:1b:db:5b:1d:9b:dd:0e:ad: | |
23 | 68:2d:c3:da:67:3c:be:6e:08:8f:a3:88:2a:d7:27: | |
24 | 0d:b6:90:f0:2d:a8:0b:54:db:95:ba:b9:0a:67:f4: | |
25 | 00:65:a0:a7:cf:81:2e:e5:6a:52:6b:18:28:74:82: | |
26 | 9f:52:14:11:96:d1:dd:23:25:74:70:81:1e:41:00: | |
27 | ec:65:3b:ac:18:30:06:f6:ed:58:d7:2c:0f:77:fa: | |
28 | 53:7c:40:02:e5:70:4a:b8:e0:b3:7b:c5:34:93:f1: | |
29 | 77:af:2f:37:a6:09:c9:e6:3d:c4:0f:15:d7:8e:6c: | |
30 | 3c:10:ab:2a:5f:38:77:b1:7d:f1:06:6d:49:1e:5a: | |
31 | 0f:26:68:fc:eb:e7:c9:b1:b7:87:4e:a6:12:de:b5: | |
32 | 5a:1b | |
33 | Exponent: 65537 (0x10001) | |
34 | X509v3 extensions: | |
35 | X509v3 Basic Constraints: | |
36 | CA:FALSE | |
37 | Netscape Comment: | |
38 | OpenSSL Generated Certificate | |
39 | X509v3 Subject Key Identifier: | |
40 | BD:79:A2:A6:3C:EC:1A:80:75:8D:60:9B:A6:F9:02:6B:C0:ED:E4:8A | |
41 | X509v3 Authority Key Identifier: | |
42 | keyid:E2:7B:60:8C:77:BB:B2:74:B8:FD:D6:2C:A9:D3:B9:35:97:12:87:EC | |
43 | ||
44 | Signature Algorithm: sha256WithRSAEncryption | |
45 | 45:62:87:35:99:a7:74:b9:de:08:7c:2f:41:f5:c8:1e:3e:df: | |
46 | c6:54:f3:e4:fa:25:a7:7b:8f:b3:1e:89:d2:83:97:50:fd:84: | |
47 | c8:53:1d:ab:9c:61:80:44:5f:72:29:6b:59:35:ab:11:45:42: | |
48 | 4f:0b:02:88:55:b9:4b:40:9a:b0:0b:ed:aa:a6:7a:44:b1:f6: | |
49 | 01:f2:3c:fd:54:d5:93:8b:9a:68:18:ed:77:c3:39:79:f5:59: | |
50 | c2:7a:7f:d0:03:b1:a5:d8:27:62:c8:33:06:7c:c5:26:32:cd: | |
51 | 92:ce:b0:2e:7f:16:e8:e3:3f:28:8e:b3:66:cd:a5:b1:64:db: | |
52 | 33:0f:c6:12:f3:22:66:0f:6f:b2:1c:fb:81:bb:a4:ad:c8:27: | |
53 | 9f:62:72:44:9b:b7:da:3c:10:0e:95:87:33:91:59:a3:0c:ca: | |
54 | d9:15:f0:de:52:25:f9:14:16:da:69:d8:af:00:87:f8:f1:6f: | |
55 | 26:07:9a:f7:4e:ad:07:23:ef:e2:aa:94:b2:45:2a:f7:55:65: | |
56 | e4:59:ee:1c:5d:69:64:4f:b3:2f:a7:54:03:36:05:10:8a:43: | |
57 | 3c:ce:8c:97:91:b6:17:4b:85:ab:a9:51:8f:de:1a:89:4b:1e: | |
58 | 5f:39:47:b3:ab:cc:14:f4:c6:ba:d3:4a:6f:6a:fe:aa:2d:2c: | |
59 | 81:53:9a:53 | |
60 | -----BEGIN CERTIFICATE----- | |
61 | MIIEPjCCAyagAwIBAgIJAJ3Ah5eg9j98MA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD | |
62 | VQQGEwJOTDEWMBQGA1UECAwNTm9vcmQtSG9sbGFuZDEcMBoGA1UECgwTRGlmZiBB | |
63 | dXRvbWF0aXNlcmluZzEWMBQGA1UECwwNU3VwcG9ydCBncm91cDEZMBcGA1UEAwwQ | |
64 | Si4gdmFuIGRlciBTdGVlbjEbMBkGCSqGSIb3DQEJARYMaW5mb0BkaWZmLm5sMB4X | |
65 | DTIwMDQwMTA5MzQzNFoXDTIxMDQwMTA5MzQzNFowgasxCzAJBgNVBAYTAk5MMRYw | |
66 | FAYDVQQIDA1Ob29yZC1Ib2xsYW5kMRIwEAYDVQQHDAlBbXN0ZXJkYW0xHDAaBgNV | |
67 | BAoME0RpZmYgQXV0b21hdGlzZXJpbmcxDzANBgNVBAsMBkNsaWVudDEZMBcGA1UE | |
68 | AwwQSi4gdmFuIGRlciBTdGVlbjEmMCQGCSqGSIb3DQEJARYXSi52YW4uZGVyLlN0 | |
69 | ZWVuQGRpZmYubmwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCkz0Ws | |
70 | Apu6AUh5UC/0WHvgR8gOEpz2nylxJORBzAJFA1FfNGnatn2DKd3H2OAFKZx+qaAx | |
71 | g1M83xf7Etoaw2tEeLMXm0T3jT4SX8wxWKcgq9PdRcdSmdJIi3KF07sEzfngt1ar | |
72 | ebdmQMfoelLt7VUb21sdm90OrWgtw9pnPL5uCI+jiCrXJw22kPAtqAtU25W6uQpn | |
73 | 9ABloKfPgS7lalJrGCh0gp9SFBGW0d0jJXRwgR5BAOxlO6wYMAb27VjXLA93+lN8 | |
74 | QALlcEq44LN7xTST8XevLzemCcnmPcQPFdeObDwQqypfOHexffEGbUkeWg8maPzr | |
75 | 58mxt4dOphLetVobAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8W | |
76 | HU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBS9eaKmPOwa | |
77 | gHWNYJum+QJrwO3kijAfBgNVHSMEGDAWgBTie2CMd7uydLj91iyp07k1lxKH7DAN | |
78 | BgkqhkiG9w0BAQsFAAOCAQEARWKHNZmndLneCHwvQfXIHj7fxlTz5Polp3uPsx6J | |
79 | 0oOXUP2EyFMdq5xhgERfcilrWTWrEUVCTwsCiFW5S0CasAvtqqZ6RLH2AfI8/VTV | |
80 | k4uaaBjtd8M5efVZwnp/0AOxpdgnYsgzBnzFJjLNks6wLn8W6OM/KI6zZs2lsWTb | |
81 | Mw/GEvMiZg9vshz7gbukrcgnn2JyRJu32jwQDpWHM5FZowzK2RXw3lIl+RQW2mnY | |
82 | rwCH+PFvJgea906tByPv4qqUskUq91Vl5FnuHF1pZE+zL6dUAzYFEIpDPM6Ml5G2 | |
83 | F0uFq6lRj94aiUseXzlHs6vMFPTGutNKb2r+qi0sgVOaUw== | |
84 | -----END CERTIFICATE----- |
0 | Certificate: | |
1 | Data: | |
2 | Version: 3 (0x2) | |
3 | Serial Number: | |
4 | 9d:c0:87:97:a0:f6:3f:7d | |
5 | Signature Algorithm: sha256WithRSAEncryption | |
6 | Issuer: C=NL, ST=Noord-Holland, O=Diff Automatisering, OU=Support group, CN=J. van der Steen/emailAddress=info@diff.nl | |
7 | Validity | |
8 | Not Before: Apr 1 09:35:37 2020 GMT | |
9 | Not After : Apr 1 09:35:37 2021 GMT | |
10 | Subject: C=NL, ST=Noord-Holland, L=Amsterdam, O=Diff Automatisering, OU=Server, CN=J. van der Steen/emailAddress=J.van.der.Steen@diff.nl | |
11 | Subject Public Key Info: | |
12 | Public Key Algorithm: rsaEncryption | |
13 | Public-Key: (2048 bit) | |
14 | Modulus: | |
15 | 00:e7:6c:7a:c1:e9:17:aa:ea:d8:32:73:66:b3:62: | |
16 | ee:3c:7d:c8:e4:3c:59:67:57:67:8d:98:61:24:31: | |
17 | 98:23:8f:ef:c3:41:2a:0f:82:1e:6a:6f:2d:00:9e: | |
18 | bf:19:ad:6b:46:42:17:c2:1e:cc:27:b5:c7:66:7a: | |
19 | a5:7b:cc:8c:15:0a:1c:d2:c5:87:23:94:88:42:5e: | |
20 | 42:9f:41:22:5a:ad:71:b2:29:54:23:39:cd:05:db: | |
21 | cf:6d:3b:8e:9a:b0:f3:e6:ca:9f:2d:39:28:d6:1c: | |
22 | 76:da:34:54:27:f9:a0:0f:1d:ae:32:30:c4:7f:9e: | |
23 | 53:18:64:27:2f:05:2b:bf:66:ce:39:52:99:8e:10: | |
24 | 1a:80:bf:5e:3a:54:fb:85:da:fc:a7:2d:90:99:42: | |
25 | c7:e2:cf:6a:db:56:1d:3b:bc:0e:97:bf:c5:d4:58: | |
26 | c4:76:33:a2:25:8c:56:94:b4:8d:a9:d3:ab:76:2a: | |
27 | f9:4c:15:de:d1:b8:23:66:3f:36:9a:4b:51:9e:1a: | |
28 | 27:e5:f0:38:a3:2a:2a:ab:cd:1c:88:7c:e4:df:82: | |
29 | 44:6f:e9:c1:0d:6f:55:98:f4:c0:06:41:ff:1f:c7: | |
30 | 30:6a:9a:14:57:73:bd:e0:a7:f7:43:0f:f4:ae:49: | |
31 | b3:48:de:42:fd:0d:be:26:e1:39:4d:24:b8:36:d7: | |
32 | 16:43 | |
33 | Exponent: 65537 (0x10001) | |
34 | X509v3 extensions: | |
35 | X509v3 Basic Constraints: | |
36 | CA:FALSE | |
37 | Netscape Comment: | |
38 | OpenSSL Generated Certificate | |
39 | X509v3 Subject Key Identifier: | |
40 | 01:84:17:EF:98:0D:F4:DD:FC:24:63:09:EF:2F:E6:BE:52:97:7C:17 | |
41 | X509v3 Authority Key Identifier: | |
42 | keyid:E2:7B:60:8C:77:BB:B2:74:B8:FD:D6:2C:A9:D3:B9:35:97:12:87:EC | |
43 | ||
44 | Signature Algorithm: sha256WithRSAEncryption | |
45 | 9a:b1:75:61:08:bb:ca:dc:b9:cd:3e:5e:30:f8:86:20:2c:e1: | |
46 | 47:41:50:c6:a3:e5:b0:d2:08:43:eb:86:9e:5c:2c:7b:4c:40: | |
47 | f9:f2:64:1d:7d:9e:f7:31:78:ef:12:05:ff:b9:4e:48:dc:0c: | |
48 | b9:9d:df:6f:3e:27:e4:a4:55:b7:61:70:9c:6d:97:30:78:5f: | |
49 | 72:7a:61:ad:68:96:e6:db:7f:fe:3a:82:52:71:88:42:08:67: | |
50 | ce:13:00:af:8f:e1:fd:bb:fd:c8:a4:cc:a9:4e:93:8f:c2:91: | |
51 | b8:e8:22:86:c0:65:36:e7:25:fb:c3:ca:bb:23:b2:33:fa:41: | |
52 | 2c:9c:e7:d8:9f:14:82:1f:a7:ea:20:77:8d:7b:82:3f:22:ea: | |
53 | 9b:87:8f:86:eb:f7:15:14:17:12:c0:90:6b:cd:7b:e1:9f:da: | |
54 | 96:aa:59:7c:21:01:98:2f:d6:19:e4:7d:60:04:d3:64:65:a3: | |
55 | 7b:a4:0f:59:d0:ce:90:1b:e0:6b:55:4f:94:d2:a5:aa:0f:c4: | |
56 | 05:b9:e8:e4:7e:11:33:db:77:3f:73:ab:ea:2d:6e:00:07:7e: | |
57 | 5a:6c:42:79:dc:06:86:85:3f:44:25:e7:d6:44:b8:b2:2e:f4: | |
58 | f1:a4:60:97:3f:b3:74:29:d7:ec:6d:f1:c4:9c:7b:e4:57:a3: | |
59 | 3c:be:17:bb | |
60 | -----BEGIN CERTIFICATE----- | |
61 | MIIEPjCCAyagAwIBAgIJAJ3Ah5eg9j99MA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD | |
62 | VQQGEwJOTDEWMBQGA1UECAwNTm9vcmQtSG9sbGFuZDEcMBoGA1UECgwTRGlmZiBB | |
63 | dXRvbWF0aXNlcmluZzEWMBQGA1UECwwNU3VwcG9ydCBncm91cDEZMBcGA1UEAwwQ | |
64 | Si4gdmFuIGRlciBTdGVlbjEbMBkGCSqGSIb3DQEJARYMaW5mb0BkaWZmLm5sMB4X | |
65 | DTIwMDQwMTA5MzUzN1oXDTIxMDQwMTA5MzUzN1owgasxCzAJBgNVBAYTAk5MMRYw | |
66 | FAYDVQQIDA1Ob29yZC1Ib2xsYW5kMRIwEAYDVQQHDAlBbXN0ZXJkYW0xHDAaBgNV | |
67 | BAoME0RpZmYgQXV0b21hdGlzZXJpbmcxDzANBgNVBAsMBlNlcnZlcjEZMBcGA1UE | |
68 | AwwQSi4gdmFuIGRlciBTdGVlbjEmMCQGCSqGSIb3DQEJARYXSi52YW4uZGVyLlN0 | |
69 | ZWVuQGRpZmYubmwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnbHrB | |
70 | 6Req6tgyc2azYu48fcjkPFlnV2eNmGEkMZgjj+/DQSoPgh5qby0Anr8ZrWtGQhfC | |
71 | HswntcdmeqV7zIwVChzSxYcjlIhCXkKfQSJarXGyKVQjOc0F289tO46asPPmyp8t | |
72 | OSjWHHbaNFQn+aAPHa4yMMR/nlMYZCcvBSu/Zs45UpmOEBqAv146VPuF2vynLZCZ | |
73 | Qsfiz2rbVh07vA6Xv8XUWMR2M6IljFaUtI2p06t2KvlMFd7RuCNmPzaaS1GeGifl | |
74 | 8DijKiqrzRyIfOTfgkRv6cENb1WY9MAGQf8fxzBqmhRXc73gp/dDD/SuSbNI3kL9 | |
75 | Db4m4TlNJLg21xZDAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8W | |
76 | HU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQBhBfvmA30 | |
77 | 3fwkYwnvL+a+Upd8FzAfBgNVHSMEGDAWgBTie2CMd7uydLj91iyp07k1lxKH7DAN | |
78 | BgkqhkiG9w0BAQsFAAOCAQEAmrF1YQi7yty5zT5eMPiGICzhR0FQxqPlsNIIQ+uG | |
79 | nlwse0xA+fJkHX2e9zF47xIF/7lOSNwMuZ3fbz4n5KRVt2FwnG2XMHhfcnphrWiW | |
80 | 5tt//jqCUnGIQghnzhMAr4/h/bv9yKTMqU6Tj8KRuOgihsBlNucl+8PKuyOyM/pB | |
81 | LJzn2J8Ugh+n6iB3jXuCPyLqm4ePhuv3FRQXEsCQa8174Z/alqpZfCEBmC/WGeR9 | |
82 | YATTZGWje6QPWdDOkBvga1VPlNKlqg/EBbno5H4RM9t3P3Or6i1uAAd+WmxCedwG | |
83 | hoU/RCXn1kS4si708aRglz+zdCnX7G3xxJx75FejPL4Xuw== | |
84 | -----END CERTIFICATE----- |
0 | Certificate: | |
1 | Data: | |
2 | Version: 3 (0x2) | |
3 | Serial Number: | |
4 | a6:11:83:6b:46:29:8a:71 | |
5 | Signature Algorithm: sha1WithRSAEncryption | |
6 | Issuer: C=NL, ST=Noord-Holland, O=Diff Automatisering, OU=Support group, CN=J. van der Steen/emailAddress=info@diff.nl | |
7 | Validity | |
8 | Not Before: Jul 3 15:11:03 2008 GMT | |
9 | Not After : Nov 19 15:11:03 2035 GMT | |
10 | Subject: C=NL, ST=Noord-Holland, L=Amsterdam, O=University of Amsterdam, OU=Server, CN=Jan Wielemaker/emailAddress=wielemak@science.uva.nl | |
11 | Subject Public Key Info: | |
12 | Public Key Algorithm: rsaEncryption | |
13 | RSA Public Key: (1024 bit) | |
14 | Modulus (1024 bit): | |
15 | 00:bd:19:49:a3:5b:44:61:19:47:31:f4:d5:8c:c2: | |
16 | bc:fc:86:08:c0:8f:d3:1c:1d:c6:f7:4f:93:f8:d1: | |
17 | 57:bf:17:d6:c5:db:34:f3:fc:af:0d:ff:0b:74:61: | |
18 | 76:14:b0:72:89:03:37:5c:d6:47:6e:c2:0c:35:f9: | |
19 | 7f:52:23:79:4b:ae:59:d8:ae:09:f5:5b:61:ed:d9: | |
20 | 29:45:80:df:fc:9b:bb:7f:5a:3b:08:dd:75:2b:29: | |
21 | e8:07:aa:49:29:ba:4c:e8:39:b3:9e:be:03:71:e7: | |
22 | b0:02:14:3a:de:29:17:86:14:68:b2:49:aa:9c:64: | |
23 | 01:60:1b:9f:7f:e0:ab:7c:8b | |
24 | Exponent: 65537 (0x10001) | |
25 | X509v3 extensions: | |
26 | X509v3 Basic Constraints: | |
27 | CA:FALSE | |
28 | Netscape Comment: | |
29 | OpenSSL Generated Certificate | |
30 | X509v3 Subject Key Identifier: | |
31 | 8F:1F:C9:B8:13:2E:8C:0A:85:B3:50:B4:57:E7:6C:09:16:5F:CE:62 | |
32 | X509v3 Authority Key Identifier: | |
33 | keyid:20:1B:40:E4:00:18:7C:E6:67:7A:80:16:FE:15:07:9E:BD:77:27:26 | |
34 | ||
35 | Signature Algorithm: sha1WithRSAEncryption | |
36 | 56:f8:23:86:30:6d:3e:ae:1f:91:1d:d5:4e:48:49:d7:cb:72: | |
37 | 74:7c:0e:34:07:f1:0d:cd:43:89:ba:ab:10:94:7b:71:2e:22: | |
38 | 61:55:ec:14:dd:56:c4:fa:ca:2b:c6:1c:6c:e8:f4:af:36:2d: | |
39 | ca:6e:ed:d8:df:b3:b2:89:57:01:d3:61:53:56:90:02:ab:a8: | |
40 | 66:c5:96:19:7e:2e:cc:70:5c:50:bf:fb:6e:e5:58:40:74:5b: | |
41 | de:d3:57:24:09:fb:32:fd:92:c1:07:7c:c0:1f:db:73:de:76: | |
42 | 6e:93:c9:e5:97:f7:fa:87:9e:07:1f:09:13:d2:86:17:3f:70: | |
43 | 0c:a2 | |
44 | -----BEGIN CERTIFICATE----- | |
45 | MIIDOzCCAqSgAwIBAgIJAKYRg2tGKYpxMA0GCSqGSIb3DQEBBQUAMIGTMQswCQYD | |
46 | VQQGEwJOTDEWMBQGA1UECBMNTm9vcmQtSG9sbGFuZDEcMBoGA1UEChMTRGlmZiBB | |
47 | dXRvbWF0aXNlcmluZzEWMBQGA1UECxMNU3VwcG9ydCBncm91cDEZMBcGA1UEAxMQ | |
48 | Si4gdmFuIGRlciBTdGVlbjEbMBkGCSqGSIb3DQEJARYMaW5mb0BkaWZmLm5sMB4X | |
49 | DTA4MDcwMzE1MTEwM1oXDTM1MTExOTE1MTEwM1owga0xCzAJBgNVBAYTAk5MMRYw | |
50 | FAYDVQQIEw1Ob29yZC1Ib2xsYW5kMRIwEAYDVQQHEwlBbXN0ZXJkYW0xIDAeBgNV | |
51 | BAoTF1VuaXZlcnNpdHkgb2YgQW1zdGVyZGFtMQ8wDQYDVQQLEwZTZXJ2ZXIxFzAV | |
52 | BgNVBAMTDkphbiBXaWVsZW1ha2VyMSYwJAYJKoZIhvcNAQkBFhd3aWVsZW1ha0Bz | |
53 | Y2llbmNlLnV2YS5ubDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvRlJo1tE | |
54 | YRlHMfTVjMK8/IYIwI/THB3G90+T+NFXvxfWxds08/yvDf8LdGF2FLByiQM3XNZH | |
55 | bsIMNfl/UiN5S65Z2K4J9Vth7dkpRYDf/Ju7f1o7CN11KynoB6pJKbpM6Dmznr4D | |
56 | ceewAhQ63ikXhhRoskmqnGQBYBuff+CrfIsCAwEAAaN7MHkwCQYDVR0TBAIwADAs | |
57 | BglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYD | |
58 | VR0OBBYEFI8fybgTLowKhbNQtFfnbAkWX85iMB8GA1UdIwQYMBaAFCAbQOQAGHzm | |
59 | Z3qAFv4VB569dycmMA0GCSqGSIb3DQEBBQUAA4GBAFb4I4YwbT6uH5Ed1U5ISdfL | |
60 | cnR8DjQH8Q3NQ4m6qxCUe3EuImFV7BTdVsT6yivGHGzo9K82Lcpu7djfs7KJVwHT | |
61 | YVNWkAKrqGbFlhl+LsxwXFC/+27lWEB0W97TVyQJ+zL9ksEHfMAf23Pedm6TyeWX | |
62 | 9/qHngcfCRPShhc/cAyi | |
63 | -----END CERTIFICATE----- |
0 | Certificate: | |
1 | Data: | |
2 | Version: 3 (0x2) | |
3 | Serial Number: | |
4 | a6:11:83:6b:46:29:8a:72 | |
5 | Signature Algorithm: sha1WithRSAEncryption | |
6 | Issuer: C=NL, ST=Noord-Holland, O=Diff Automatisering, OU=Support group, CN=J. van der Steen/emailAddress=info@diff.nl | |
7 | Validity | |
8 | Not Before: Jul 3 15:11:14 2008 GMT | |
9 | Not After : Nov 19 15:11:14 2035 GMT | |
10 | Subject: C=NL, ST=Noord-Holland, L=Amsterdam, O=University of Amsterdam, OU=Client, CN=Jan Wielemaker/emailAddress=wielemak@science.uva.nl | |
11 | Subject Public Key Info: | |
12 | Public Key Algorithm: rsaEncryption | |
13 | RSA Public Key: (1024 bit) | |
14 | Modulus (1024 bit): | |
15 | 00:b0:f8:4b:6f:fb:04:72:e5:79:5e:07:14:45:d3: | |
16 | 9d:4f:2f:ab:ee:ba:6e:07:52:ce:34:37:b5:4b:31: | |
17 | a8:0f:02:a5:24:bb:41:37:6c:2f:17:e2:7f:fe:c0: | |
18 | 2a:84:6d:e7:3b:fb:b9:4a:df:09:ea:0d:47:2a:d0: | |
19 | fe:7b:82:12:ca:6b:5f:70:bb:a5:91:a3:d0:f9:4c: | |
20 | c7:7b:4b:8d:7f:a7:6a:f9:27:34:32:43:7b:f2:e4: | |
21 | d6:8f:d2:42:ed:21:28:1c:67:62:6e:84:75:ab:da: | |
22 | 90:a8:1e:09:70:47:c5:51:ae:d1:74:88:73:74:e7: | |
23 | 65:f3:ea:4d:e0:75:a6:64:6f | |
24 | Exponent: 65537 (0x10001) | |
25 | X509v3 extensions: | |
26 | X509v3 Basic Constraints: | |
27 | CA:FALSE | |
28 | Netscape Comment: | |
29 | OpenSSL Generated Certificate | |
30 | X509v3 Subject Key Identifier: | |
31 | F1:3E:D8:C4:80:01:24:70:79:03:AB:76:81:A4:4F:50:A8:F1:B2:FD | |
32 | X509v3 Authority Key Identifier: | |
33 | keyid:20:1B:40:E4:00:18:7C:E6:67:7A:80:16:FE:15:07:9E:BD:77:27:26 | |
34 | ||
35 | Signature Algorithm: sha1WithRSAEncryption | |
36 | 2d:9f:13:8b:ca:d6:0a:f0:ef:75:52:ab:a0:fe:6f:f1:14:16: | |
37 | f9:4e:f5:77:ac:55:9b:bb:31:d3:fa:e5:4f:9a:83:91:7d:c5: | |
38 | 90:b1:94:d1:1b:3b:a2:b4:fa:5f:43:79:20:ec:b2:48:61:fc: | |
39 | bf:75:25:75:64:2d:c6:02:61:4b:4a:d9:50:eb:bc:ba:e7:cb: | |
40 | 31:91:f2:18:6b:62:8f:e4:29:ea:83:29:54:53:05:40:5c:86: | |
41 | 11:d2:56:0d:4a:39:f6:b4:f0:78:86:98:15:da:3a:cd:86:7e: | |
42 | c0:bc:71:dc:7d:69:f8:0b:56:17:a3:3b:6d:e3:65:73:1d:64: | |
43 | 21:f0 | |
44 | -----BEGIN CERTIFICATE----- | |
45 | MIIDOzCCAqSgAwIBAgIJAKYRg2tGKYpyMA0GCSqGSIb3DQEBBQUAMIGTMQswCQYD | |
46 | VQQGEwJOTDEWMBQGA1UECBMNTm9vcmQtSG9sbGFuZDEcMBoGA1UEChMTRGlmZiBB | |
47 | dXRvbWF0aXNlcmluZzEWMBQGA1UECxMNU3VwcG9ydCBncm91cDEZMBcGA1UEAxMQ | |
48 | Si4gdmFuIGRlciBTdGVlbjEbMBkGCSqGSIb3DQEJARYMaW5mb0BkaWZmLm5sMB4X | |
49 | DTA4MDcwMzE1MTExNFoXDTM1MTExOTE1MTExNFowga0xCzAJBgNVBAYTAk5MMRYw | |
50 | FAYDVQQIEw1Ob29yZC1Ib2xsYW5kMRIwEAYDVQQHEwlBbXN0ZXJkYW0xIDAeBgNV | |
51 | BAoTF1VuaXZlcnNpdHkgb2YgQW1zdGVyZGFtMQ8wDQYDVQQLEwZDbGllbnQxFzAV | |
52 | BgNVBAMTDkphbiBXaWVsZW1ha2VyMSYwJAYJKoZIhvcNAQkBFhd3aWVsZW1ha0Bz | |
53 | Y2llbmNlLnV2YS5ubDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsPhLb/sE | |
54 | cuV5XgcURdOdTy+r7rpuB1LONDe1SzGoDwKlJLtBN2wvF+J//sAqhG3nO/u5St8J | |
55 | 6g1HKtD+e4ISymtfcLulkaPQ+UzHe0uNf6dq+Sc0MkN78uTWj9JC7SEoHGdiboR1 | |
56 | q9qQqB4JcEfFUa7RdIhzdOdl8+pN4HWmZG8CAwEAAaN7MHkwCQYDVR0TBAIwADAs | |
57 | BglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYD | |
58 | VR0OBBYEFPE+2MSAASRweQOrdoGkT1Co8bL9MB8GA1UdIwQYMBaAFCAbQOQAGHzm | |
59 | Z3qAFv4VB569dycmMA0GCSqGSIb3DQEBBQUAA4GBAC2fE4vK1grw73VSq6D+b/EU | |
60 | FvlO9XesVZu7MdP65U+ag5F9xZCxlNEbO6K0+l9DeSDsskhh/L91JXVkLcYCYUtK | |
61 | 2VDrvLrnyzGR8hhrYo/kKeqDKVRTBUBchhHSVg1KOfa08HiGmBXaOs2GfsC8cdx9 | |
62 | afgLVhejO23jZXMdZCHw | |
63 | -----END CERTIFICATE----- |
0 | -----BEGIN RSA PRIVATE KEY----- | |
1 | Proc-Type: 4,ENCRYPTED | |
2 | DEK-Info: DES-EDE3-CBC,451F2D191DB34CCE | |
3 | ||
4 | KjPvyYKFWfUegzyq8fBtsDGaGDfLXeZ/RWHnTWSSoUXzODLrbOzKguwLES89EltO | |
5 | 9zuMBBWjRU2eNFu06Eb1KelDI69WvIpL5J1/rQptluKSYRXP+2GbtQsNEqtLBwE4 | |
6 | oLEWWtr/PoJ9CUQImYtmea4rG+TeS9eJSIV0OCrfg/UW18jknSUbnr/YczU9i77Q | |
7 | x2ZDE6WIsxv1H8gNQF13wHOoz9K6zzJDOWxDWaQoogsddXIJEnvDp5vH9seGyfzF | |
8 | W/uxobS367uAd2NOYWyv960zc6EEBMeHcGZu0/zeoqiEoD9D4DBVx/P/4ZcWjh6L | |
9 | rRnD3Y4pG0UTND1EJQwEq7Ep2ZxRztz3rIVhcpLQtwNSCRvdg2tPR1AftXPzd84D | |
10 | ZG0nJMpvvo3FwueXHKuEenZbC8C2rDBQwBqxpgJZxMOJkYr1vqaApWs/jncjqGgU | |
11 | tDAjSZ8OpdQxl4QwbLD8AA3Sieplwh2AANlnqQndy+5qsHThO4CjgCZV62i3tlix | |
12 | +voydAknHxBVq2O7fVBDveGmr2J2uYezTaWTTQrQ/EdpZjp5hcXamuimMKw0VFkh | |
13 | mUrFnos/r5mbcXdn1lAosHiU9sEhXokrOBo7AO0k+EcLf3RsdSBV/1k6tRYIuj11 | |
14 | Dx6IKCVu+jlni9CzVa4YD9wv8KqoY0cedLNZP9QdlExJZ5UIuagApyM0sijQA+X1 | |
15 | EXcuomvVrNLyC68kVySbSqae9gMygCBsQt9ZSln4GkAWgmJcSVU53hckGdh/Fk0l | |
16 | bWTXGuaQvYdsVlXCtiTMW17pSeIZ43eK14s23JtH5WtuFGlNWxE92w== | |
17 | -----END RSA PRIVATE KEY----- | |
0 | -----BEGIN ENCRYPTED PRIVATE KEY----- | |
1 | MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIQIKJS+m0aHQCAggA | |
2 | MBQGCCqGSIb3DQMHBAjpS40JcLsn6gSCBMgq47RGhd+pzf9kWFX47wB+s2oUOFhQ | |
3 | tliBdHa523eG7enigUHrufv7eNiQ9KNpWGKXSV9eb2HBWmrizdJu93s48CzxDXVU | |
4 | hmglHf339bGh89U2MleJcIoeqSeqLHvYb8P28soJ0R5zaW32XgxTy47jGOjlAzac | |
5 | c7xm0YyrV4Tj94J7AKQAsyU7ScyYDe9SSlUIWpmn/dRAz8F6uA4spHRixpXywZPI | |
6 | 8pab9WvvB04U6BgT5g0qAKmvssADyhAtguEjgEBjZcOxFWpL4kgY4SEezpez/12t | |
7 | HBUNj0iNV27POTg+jL9LHktjTcqgYxOtSyl/W3NYLFxrkh3Ww4cz7MxzPkOVUOeb | |
8 | LKWEerc8IEaIMzSh+LxbFKgttUxscU6ov9YlGUZx5upqhrT9tQHjhvGtXVUrlSOz | |
9 | 1b9BFSq+D23HxugZVXbhabtPW6gnL3z8U2nLIrey2Obt2WjQIn2TiR1uLrcuYz2D | |
10 | EM55EkinW0v7pawok3+d8D5inHc/sOLPyVYcwma84zQ+9Mhlw0DfdiRd/rH5ROcF | |
11 | yc8WA1+BAWvPscJzuqW7nYvpTX6i6FEQPgX8iuz+X2E+M2SSFBM0Jyw1B4Ggsl6u | |
12 | H0zPpQMO8uGxRXl7JXigNdTruIHk0Xwf6fx5Lo+XOEk7zoAyq3LNTQXggjBReAKJ | |
13 | V8qvk4lagBQeEdF8a5YIa2jBhqjc4FlWRAbMZ4f2vVH+LAk+J2qjlbJ3U7+H1w7I | |
14 | A61c7BFdlkhWYuxjx/06khQbx5o46zVT19ykBjOpigJ8fRB2gQyr8346k1i/WZ7/ | |
15 | IVJVjWS0jM+o8a2Fin/XxPcKWAJ5t+ePcxl2cytmf9Q703eMdPHjFp2ApPVMGaRC | |
16 | Zkzk/LIgEzXuFIMkLb8+KXKHe1+kRMJDjgT5Nq771K1aE87KWM31qUIfGeLBwUh5 | |
17 | YIwLRV5U03Vep7bcwoLUyxUf5i0y/ePBhG01Epng1KFLcIZ3GSUJ6wsrVETE1ggq | |
18 | IM9py9gYhMiuPRZ5VLEP1eJoTSsDv47oh58Tp5REPOjmMSTBYdxG1XxESQBiSlr+ | |
19 | 2ZrE5i49Zn3Bbz5lkgNE/dpcGunn+cIBXGGcODomtbcKUACWXnOK2+4OsaKLUFr7 | |
20 | S+AUP9sNigUDPWZuQQZtoJim1+YZyR+77BXfkeX39KPcsvE7O7cZ/LBFmZRLkRvv | |
21 | 2E7n6GymUYrY2DgFiTSfUGafBtb24ALR8xEJ6CmGOeGIl0pGfS3ra7Ar9s2NdHPN | |
22 | yfE0fkgXnXW+misEamPU0SuTXKutTg/+NyCAw9qZrI0X17W8bTeb2xFbi3QNm3Qe | |
23 | sYgUF/9Huia8I+LVvv8dkHZ9ediw1hmAliGOuREb/e/v7d0EshGpxUouNGKcyICX | |
24 | GArW0cEwIjQpm8M+jOigXs49QmWiejuWclEpap6pqUXC15oMpKloJYpinIzyqYft | |
25 | v/P4XhMK5pWHXRRbWzgXGjXS2leMP+uEgwTzROwr3ptLKZUN1e8wpg0HgpVU1YGh | |
26 | ZriiP8R6FLUlPBwd69oqybiqEhDLepbXloegN9uvS5LJM73hIuEZuSW0f/lGOM35 | |
27 | fvDqBrcoo3DJTNUBxh/BB0jwoJzeXC6oivIrlMl8nf5fRzIcFcei04PUK5UMSczh | |
28 | 5Pk= | |
29 | -----END ENCRYPTED PRIVATE KEY----- |
1 | 1 | Data: |
2 | 2 | Version: 3 (0x2) |
3 | 3 | Serial Number: |
4 | a6:11:83:6b:46:29:8a:71 | |
5 | Signature Algorithm: sha1WithRSAEncryption | |
4 | 9d:c0:87:97:a0:f6:3f:7d | |
5 | Signature Algorithm: sha256WithRSAEncryption | |
6 | 6 | Issuer: C=NL, ST=Noord-Holland, O=Diff Automatisering, OU=Support group, CN=J. van der Steen/emailAddress=info@diff.nl |
7 | 7 | Validity |
8 | Not Before: Jul 3 15:11:03 2008 GMT | |
9 | Not After : Nov 19 15:11:03 2035 GMT | |
10 | Subject: C=NL, ST=Noord-Holland, L=Amsterdam, O=University of Amsterdam, OU=Server, CN=Jan Wielemaker/emailAddress=wielemak@science.uva.nl | |
8 | Not Before: Apr 1 09:35:37 2020 GMT | |
9 | Not After : Apr 1 09:35:37 2021 GMT | |
10 | Subject: C=NL, ST=Noord-Holland, L=Amsterdam, O=Diff Automatisering, OU=Server, CN=J. van der Steen/emailAddress=J.van.der.Steen@diff.nl | |
11 | 11 | Subject Public Key Info: |
12 | 12 | Public Key Algorithm: rsaEncryption |
13 | RSA Public Key: (1024 bit) | |
14 | Modulus (1024 bit): | |
15 | 00:bd:19:49:a3:5b:44:61:19:47:31:f4:d5:8c:c2: | |
16 | bc:fc:86:08:c0:8f:d3:1c:1d:c6:f7:4f:93:f8:d1: | |
17 | 57:bf:17:d6:c5:db:34:f3:fc:af:0d:ff:0b:74:61: | |
18 | 76:14:b0:72:89:03:37:5c:d6:47:6e:c2:0c:35:f9: | |
19 | 7f:52:23:79:4b:ae:59:d8:ae:09:f5:5b:61:ed:d9: | |
20 | 29:45:80:df:fc:9b:bb:7f:5a:3b:08:dd:75:2b:29: | |
21 | e8:07:aa:49:29:ba:4c:e8:39:b3:9e:be:03:71:e7: | |
22 | b0:02:14:3a:de:29:17:86:14:68:b2:49:aa:9c:64: | |
23 | 01:60:1b:9f:7f:e0:ab:7c:8b | |
13 | Public-Key: (2048 bit) | |
14 | Modulus: | |
15 | 00:e7:6c:7a:c1:e9:17:aa:ea:d8:32:73:66:b3:62: | |
16 | ee:3c:7d:c8:e4:3c:59:67:57:67:8d:98:61:24:31: | |
17 | 98:23:8f:ef:c3:41:2a:0f:82:1e:6a:6f:2d:00:9e: | |
18 | bf:19:ad:6b:46:42:17:c2:1e:cc:27:b5:c7:66:7a: | |
19 | a5:7b:cc:8c:15:0a:1c:d2:c5:87:23:94:88:42:5e: | |
20 | 42:9f:41:22:5a:ad:71:b2:29:54:23:39:cd:05:db: | |
21 | cf:6d:3b:8e:9a:b0:f3:e6:ca:9f:2d:39:28:d6:1c: | |
22 | 76:da:34:54:27:f9:a0:0f:1d:ae:32:30:c4:7f:9e: | |
23 | 53:18:64:27:2f:05:2b:bf:66:ce:39:52:99:8e:10: | |
24 | 1a:80:bf:5e:3a:54:fb:85:da:fc:a7:2d:90:99:42: | |
25 | c7:e2:cf:6a:db:56:1d:3b:bc:0e:97:bf:c5:d4:58: | |
26 | c4:76:33:a2:25:8c:56:94:b4:8d:a9:d3:ab:76:2a: | |
27 | f9:4c:15:de:d1:b8:23:66:3f:36:9a:4b:51:9e:1a: | |
28 | 27:e5:f0:38:a3:2a:2a:ab:cd:1c:88:7c:e4:df:82: | |
29 | 44:6f:e9:c1:0d:6f:55:98:f4:c0:06:41:ff:1f:c7: | |
30 | 30:6a:9a:14:57:73:bd:e0:a7:f7:43:0f:f4:ae:49: | |
31 | b3:48:de:42:fd:0d:be:26:e1:39:4d:24:b8:36:d7: | |
32 | 16:43 | |
24 | 33 | Exponent: 65537 (0x10001) |
25 | 34 | X509v3 extensions: |
26 | 35 | X509v3 Basic Constraints: |
28 | 37 | Netscape Comment: |
29 | 38 | OpenSSL Generated Certificate |
30 | 39 | X509v3 Subject Key Identifier: |
31 | 8F:1F:C9:B8:13:2E:8C:0A:85:B3:50:B4:57:E7:6C:09:16:5F:CE:62 | |
40 | 01:84:17:EF:98:0D:F4:DD:FC:24:63:09:EF:2F:E6:BE:52:97:7C:17 | |
32 | 41 | X509v3 Authority Key Identifier: |
33 | keyid:20:1B:40:E4:00:18:7C:E6:67:7A:80:16:FE:15:07:9E:BD:77:27:26 | |
42 | keyid:E2:7B:60:8C:77:BB:B2:74:B8:FD:D6:2C:A9:D3:B9:35:97:12:87:EC | |
34 | 43 | |
35 | Signature Algorithm: sha1WithRSAEncryption | |
36 | 56:f8:23:86:30:6d:3e:ae:1f:91:1d:d5:4e:48:49:d7:cb:72: | |
37 | 74:7c:0e:34:07:f1:0d:cd:43:89:ba:ab:10:94:7b:71:2e:22: | |
38 | 61:55:ec:14:dd:56:c4:fa:ca:2b:c6:1c:6c:e8:f4:af:36:2d: | |
39 | ca:6e:ed:d8:df:b3:b2:89:57:01:d3:61:53:56:90:02:ab:a8: | |
40 | 66:c5:96:19:7e:2e:cc:70:5c:50:bf:fb:6e:e5:58:40:74:5b: | |
41 | de:d3:57:24:09:fb:32:fd:92:c1:07:7c:c0:1f:db:73:de:76: | |
42 | 6e:93:c9:e5:97:f7:fa:87:9e:07:1f:09:13:d2:86:17:3f:70: | |
43 | 0c:a2 | |
44 | Signature Algorithm: sha256WithRSAEncryption | |
45 | 9a:b1:75:61:08:bb:ca:dc:b9:cd:3e:5e:30:f8:86:20:2c:e1: | |
46 | 47:41:50:c6:a3:e5:b0:d2:08:43:eb:86:9e:5c:2c:7b:4c:40: | |
47 | f9:f2:64:1d:7d:9e:f7:31:78:ef:12:05:ff:b9:4e:48:dc:0c: | |
48 | b9:9d:df:6f:3e:27:e4:a4:55:b7:61:70:9c:6d:97:30:78:5f: | |
49 | 72:7a:61:ad:68:96:e6:db:7f:fe:3a:82:52:71:88:42:08:67: | |
50 | ce:13:00:af:8f:e1:fd:bb:fd:c8:a4:cc:a9:4e:93:8f:c2:91: | |
51 | b8:e8:22:86:c0:65:36:e7:25:fb:c3:ca:bb:23:b2:33:fa:41: | |
52 | 2c:9c:e7:d8:9f:14:82:1f:a7:ea:20:77:8d:7b:82:3f:22:ea: | |
53 | 9b:87:8f:86:eb:f7:15:14:17:12:c0:90:6b:cd:7b:e1:9f:da: | |
54 | 96:aa:59:7c:21:01:98:2f:d6:19:e4:7d:60:04:d3:64:65:a3: | |
55 | 7b:a4:0f:59:d0:ce:90:1b:e0:6b:55:4f:94:d2:a5:aa:0f:c4: | |
56 | 05:b9:e8:e4:7e:11:33:db:77:3f:73:ab:ea:2d:6e:00:07:7e: | |
57 | 5a:6c:42:79:dc:06:86:85:3f:44:25:e7:d6:44:b8:b2:2e:f4: | |
58 | f1:a4:60:97:3f:b3:74:29:d7:ec:6d:f1:c4:9c:7b:e4:57:a3: | |
59 | 3c:be:17:bb | |
44 | 60 | -----BEGIN CERTIFICATE----- |
45 | MIIDOzCCAqSgAwIBAgIJAKYRg2tGKYpxMA0GCSqGSIb3DQEBBQUAMIGTMQswCQYD | |
46 | VQQGEwJOTDEWMBQGA1UECBMNTm9vcmQtSG9sbGFuZDEcMBoGA1UEChMTRGlmZiBB | |
47 | dXRvbWF0aXNlcmluZzEWMBQGA1UECxMNU3VwcG9ydCBncm91cDEZMBcGA1UEAxMQ | |
61 | MIIEPjCCAyagAwIBAgIJAJ3Ah5eg9j99MA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD | |
62 | VQQGEwJOTDEWMBQGA1UECAwNTm9vcmQtSG9sbGFuZDEcMBoGA1UECgwTRGlmZiBB | |
63 | dXRvbWF0aXNlcmluZzEWMBQGA1UECwwNU3VwcG9ydCBncm91cDEZMBcGA1UEAwwQ | |
48 | 64 | Si4gdmFuIGRlciBTdGVlbjEbMBkGCSqGSIb3DQEJARYMaW5mb0BkaWZmLm5sMB4X |
49 | DTA4MDcwMzE1MTEwM1oXDTM1MTExOTE1MTEwM1owga0xCzAJBgNVBAYTAk5MMRYw | |
50 | FAYDVQQIEw1Ob29yZC1Ib2xsYW5kMRIwEAYDVQQHEwlBbXN0ZXJkYW0xIDAeBgNV | |
51 | BAoTF1VuaXZlcnNpdHkgb2YgQW1zdGVyZGFtMQ8wDQYDVQQLEwZTZXJ2ZXIxFzAV | |
52 | BgNVBAMTDkphbiBXaWVsZW1ha2VyMSYwJAYJKoZIhvcNAQkBFhd3aWVsZW1ha0Bz | |
53 | Y2llbmNlLnV2YS5ubDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvRlJo1tE | |
54 | YRlHMfTVjMK8/IYIwI/THB3G90+T+NFXvxfWxds08/yvDf8LdGF2FLByiQM3XNZH | |
55 | bsIMNfl/UiN5S65Z2K4J9Vth7dkpRYDf/Ju7f1o7CN11KynoB6pJKbpM6Dmznr4D | |
56 | ceewAhQ63ikXhhRoskmqnGQBYBuff+CrfIsCAwEAAaN7MHkwCQYDVR0TBAIwADAs | |
57 | BglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYD | |
58 | VR0OBBYEFI8fybgTLowKhbNQtFfnbAkWX85iMB8GA1UdIwQYMBaAFCAbQOQAGHzm | |
59 | Z3qAFv4VB569dycmMA0GCSqGSIb3DQEBBQUAA4GBAFb4I4YwbT6uH5Ed1U5ISdfL | |
60 | cnR8DjQH8Q3NQ4m6qxCUe3EuImFV7BTdVsT6yivGHGzo9K82Lcpu7djfs7KJVwHT | |
61 | YVNWkAKrqGbFlhl+LsxwXFC/+27lWEB0W97TVyQJ+zL9ksEHfMAf23Pedm6TyeWX | |
62 | 9/qHngcfCRPShhc/cAyi | |
65 | DTIwMDQwMTA5MzUzN1oXDTIxMDQwMTA5MzUzN1owgasxCzAJBgNVBAYTAk5MMRYw | |
66 | FAYDVQQIDA1Ob29yZC1Ib2xsYW5kMRIwEAYDVQQHDAlBbXN0ZXJkYW0xHDAaBgNV | |
67 | BAoME0RpZmYgQXV0b21hdGlzZXJpbmcxDzANBgNVBAsMBlNlcnZlcjEZMBcGA1UE | |
68 | AwwQSi4gdmFuIGRlciBTdGVlbjEmMCQGCSqGSIb3DQEJARYXSi52YW4uZGVyLlN0 | |
69 | ZWVuQGRpZmYubmwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnbHrB | |
70 | 6Req6tgyc2azYu48fcjkPFlnV2eNmGEkMZgjj+/DQSoPgh5qby0Anr8ZrWtGQhfC | |
71 | HswntcdmeqV7zIwVChzSxYcjlIhCXkKfQSJarXGyKVQjOc0F289tO46asPPmyp8t | |
72 | OSjWHHbaNFQn+aAPHa4yMMR/nlMYZCcvBSu/Zs45UpmOEBqAv146VPuF2vynLZCZ | |
73 | Qsfiz2rbVh07vA6Xv8XUWMR2M6IljFaUtI2p06t2KvlMFd7RuCNmPzaaS1GeGifl | |
74 | 8DijKiqrzRyIfOTfgkRv6cENb1WY9MAGQf8fxzBqmhRXc73gp/dDD/SuSbNI3kL9 | |
75 | Db4m4TlNJLg21xZDAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8W | |
76 | HU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQBhBfvmA30 | |
77 | 3fwkYwnvL+a+Upd8FzAfBgNVHSMEGDAWgBTie2CMd7uydLj91iyp07k1lxKH7DAN | |
78 | BgkqhkiG9w0BAQsFAAOCAQEAmrF1YQi7yty5zT5eMPiGICzhR0FQxqPlsNIIQ+uG | |
79 | nlwse0xA+fJkHX2e9zF47xIF/7lOSNwMuZ3fbz4n5KRVt2FwnG2XMHhfcnphrWiW | |
80 | 5tt//jqCUnGIQghnzhMAr4/h/bv9yKTMqU6Tj8KRuOgihsBlNucl+8PKuyOyM/pB | |
81 | LJzn2J8Ugh+n6iB3jXuCPyLqm4ePhuv3FRQXEsCQa8174Z/alqpZfCEBmC/WGeR9 | |
82 | YATTZGWje6QPWdDOkBvga1VPlNKlqg/EBbno5H4RM9t3P3Or6i1uAAd+WmxCedwG | |
83 | hoU/RCXn1kS4si708aRglz+zdCnX7G3xxJx75FejPL4Xuw== | |
63 | 84 | -----END CERTIFICATE----- |
0 | -----BEGIN RSA PRIVATE KEY----- | |
1 | Proc-Type: 4,ENCRYPTED | |
2 | DEK-Info: DES-EDE3-CBC,E3E8E2A5E1403F5E | |
3 | ||
4 | Q5tlYh5soGvk/arzLBEawOWJHRF9ISivcjlWPE9fqH3pkvvthA7ntCEjKSXlzRPA | |
5 | eNP3yZVL59zmgyZiS3QlpX4XwEugoSmXaLiDY3AWKBrQ6G+KHipJ+LmDPzupbPia | |
6 | 078nR6jIDPkS99lg3ogk27UbyI2E9iPoVHKsWiX/L0IvdxB8NjsHdwa+97EoVXRB | |
7 | pyLTpEuXQHopqtDikMlfinE1u/yhybrXRNBncQ083+rZ2gTDGQsm7AXtynPRvlgG | |
8 | BaJl0FGeruVihbJ5o0D8xzN2IdHKsDtde/udyE8njD3f+yLDuM91qHnoeefm8J+X | |
9 | Txc+mQ3srqiaI5ZyYVZG728lEHeNooddIsrrM2VGkd9CveGzYCuMOc4LUTrLorb9 | |
10 | wV9te2hTRICI+b+7i7yN6yVKcsrIX249HNFQ2E6i5tZcyZIrL2TzL/niS5g+jlwN | |
11 | FLk2WgldG3kHGhFzNWDFkM64YShYHWGPvysUYx0/hcixrJsXJV8AbmdsG6Mzw3XJ | |
12 | z4A9dPUTyYi7vqPzm6aMohZp/RSY0D6o6qBYtDL/toj5btzEf1T2jzwZwPovRWwT | |
13 | 5sPxWts2g7bqhMnpRCwo+pEd51sBZAFz4MOMEJR7zzvO9mcAWvO3zopRH0ugzuwl | |
14 | yHXSXPdU/04Auv63EEiZO01/PDNm6KAvAsEIkj9x6n678wJ609J+G2IC0E7i7ZfQ | |
15 | lkcX18AWq7ydcxAygfl/RT8tOKhTpXRemqu9JU7c9yjD3HqRpOW6VrPsLXKXL4UC | |
16 | 6R1n88SinCCnPMSVeNhhJrpI1L3XgJPb9zh9I7tpE7o2KvwBoc8/rg== | |
17 | -----END RSA PRIVATE KEY----- | |
18 | -----BEGIN CERTIFICATE REQUEST----- | |
19 | MIICLjCCAZcCAQAwga0xCzAJBgNVBAYTAk5MMRYwFAYDVQQIEw1Ob29yZC1Ib2xs | |
20 | YW5kMRIwEAYDVQQHEwlBbXN0ZXJkYW0xIDAeBgNVBAoTF1VuaXZlcnNpdHkgb2Yg | |
21 | QW1zdGVyZGFtMQ8wDQYDVQQLEwZTZXJ2ZXIxFzAVBgNVBAMTDkphbiBXaWVsZW1h | |
22 | a2VyMSYwJAYJKoZIhvcNAQkBFhd3aWVsZW1ha0BzY2llbmNlLnV2YS5ubDCBnzAN | |
23 | BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvRlJo1tEYRlHMfTVjMK8/IYIwI/THB3G | |
24 | 90+T+NFXvxfWxds08/yvDf8LdGF2FLByiQM3XNZHbsIMNfl/UiN5S65Z2K4J9Vth | |
25 | 7dkpRYDf/Ju7f1o7CN11KynoB6pJKbpM6Dmznr4DceewAhQ63ikXhhRoskmqnGQB | |
26 | YBuff+CrfIsCAwEAAaBAMBYGCSqGSIb3DQEJBzEJEwdub290amVzMCYGCSqGSIb3 | |
27 | DQEJAjEZExdVbml2ZXJzaXR5IG9mIEFtc3RlcmRhbTANBgkqhkiG9w0BAQQFAAOB | |
28 | gQBophWFXJO86vms/b86illcnZTb/vfRM9aKT4DrfpOjgW6Dmk95VwPqGFIoxfnd | |
29 | yRokzKvOoW2JMZ+u9Jz7q1R2AEkRivRjVoSY8Cd+YqsFBiD5vt8eHI8jqqoMEl2D | |
30 | iQWjre7hFij7bY6flVerTV0dsz6MHRPbzAkvJohAceHgKQ== | |
31 | -----END CERTIFICATE REQUEST----- | |
0 | -----BEGIN ENCRYPTED PRIVATE KEY----- | |
1 | MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIUZoWaoXwEL4CAggA | |
2 | MBQGCCqGSIb3DQMHBAiLJma8RXDpzQSCBMhVAz+QXJhiJw5epX1BiJL7j/09s8mb | |
3 | uXxgpJhE40kAbwAvykq6FOmjubrE6bPx0n8Dk4b/KroKjjS6DV0AX4jvrep43T/z | |
4 | IRHqjDdYOHAyIi9yXQGsFkeHdIEo7vXU1zA4Om+K3wreK07Pz4YfiKAWF6/6xJj4 | |
5 | fue8zXGgLB6fiWQs4EbH7EiCYgVuypU50sUa/AnpWXe9ITVBssjeHCjTphxHtL8j | |
6 | rT+JBv0XpdAYcBOX4irk8zEq+432/RL7DPi2ercBpDQeaAsMfyTOrhptUkAcyj0/ | |
7 | PTFsrxchtyS5HQbR7yKhio2bxAGCinsWD/WSLU95RzT83rSgMth4q9nURqVKE7Y1 | |
8 | LsnMa9YIyITdKPSzyA8rmcylghK23PDGhYDw1pZIhbpcGNjiLSyI4js68urIwpK1 | |
9 | xdQv9Oouq8U5SJNLH7jNJVIfmtOIVnJEy+GoSgNtQn7f9LrLfZtccWNsejuKxvDi | |
10 | NKmhrUvoMLD7lN6CH7CWtUe3o523Q/a4XXJYnTrFz4viKS8ig5ljfzOzq1XimJJb | |
11 | /EmKStoiRIeTC0MBmCu0uo43oaT+AihvZZB+TPUV/L0T0kV7rd0n59RxFmwOlO7j | |
12 | iSOz1cy2jmILiDh4gAdH43H6WG6I38q23rLyt/EMVh/1DgJlndfdVVKk4VvFT/Bx | |
13 | MjgEEvrf/VC7idy6mQea4tWJ+lXag64phwXt0zja3v/tVKhVJPyFlFLgslve7ZKt | |
14 | 8r8nFTFcZSyVt2Qi+kRL3Iuu/lRkvOcaeK5VdtjV4PV+Pmk6VvecptSr2pkfUTdy | |
15 | wFgKWBjwruINfcIoFyegL4cUyWWcQDwSfWTT0WAWt6kLvf0xjK6jjcFvFn46RHFf | |
16 | zQbnmyqo20nKRhR88EJTuqevyLRUG1EBQwSyWuq4m/5XTy5nFIWcWIx6bF/hsk9C | |
17 | ZB/aq2+4pw6oZlEb7yXdaLvlRXuhmiqUbff2xW/lcG77AWDm3as0J7O6OZg+7170 | |
18 | DdP99viL/K1+O0gZZDkl/YGdJgy6eHA0GXC1Xz6vARRxexxwvJQfXb5R2FnMENxm | |
19 | sCTqZwIXYPCWnQ7IoRUHl4q8uMTdxCZiIoXglzX+O5XTxPUOYk8HeEohIppAt5l/ | |
20 | dB9lMfQmM/GEOXYlI8gEPNJ4vVBiulpzbIfHT9qAZVpH4+++Hwo6xYT2z/L46Ax2 | |
21 | IlFS1TMd9f9PkPf/Vh+aezcw6YfIUEJ6YTuOjmSgSpPshQKC4mgTtIayOEJTuBih | |
22 | EAf+nq940RaKlittUi5s1YZbxwkV+YXz6DsK6L4UypmU2Dlg/aWaEFQsIUULSNgi | |
23 | FrlzJZwRJdFhcQhvkr2WUk5JxcScydPRqhhk7ZL2EVzgGqdNfg3aq9jZGBQYthqL | |
24 | DxcSQcrolOj2p2DUAUGJdtBGpzddz77qB81E4Sy3rsratycaDBARADORqrPEXdSi | |
25 | DBhSFCCARpZtIxALPjANLL8Jx1kz9H4bZcp0z+M9l+pSfjpXEbWOKD/OpCqlvhCK | |
26 | 4EiLhYYoUZWPQeZf0khgIZk9n0PvnUb5oJYONdnCb4fBgEDUMQ0wijCw3D5QMC0Y | |
27 | Es2tHhIGqwxjaI5SmmOET1tYznInffvsWhvN8WESirISrjM9KZx608bpHRV47oXi | |
28 | O7g= | |
29 | -----END ENCRYPTED PRIVATE KEY----- |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2007-2018, University of Amsterdam | |
5 | Copyright (c) 2007-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
37 | 37 | :- use_module(library(ssl), |
38 | 38 | [ ssl_context/3, |
39 | 39 | ssl_secure_ciphers/1, |
40 | ssl_property/2, | |
40 | 41 | ssl_set_options/3, |
41 | 42 | ssl_negotiate/5 |
42 | 43 | ]). |
53 | 54 | |
54 | 55 | :- autoload(library(lists),[select/3]). |
55 | 56 | :- autoload(library(option),[option/2,option/3]). |
57 | :- autoload(library(apply), [include/3]). | |
56 | 58 | :- autoload(library(http/http_header),[http_read_reply_header/2]). |
57 | 59 | :- autoload(library(http/thread_httpd),[http_enough_workers/3]). |
58 | 60 | |
96 | 98 | add_secure_ciphers(SSLOptions0, SSLOptions1), |
97 | 99 | disable_sslv3(SSLOptions1, SSLOptions), |
98 | 100 | make_socket(Port, Socket, Options1), |
99 | ssl_context(server, SSL0, M:SSLOptions), | |
100 | ( http:ssl_server_create_hook(SSL0, SSL, Options1) | |
101 | -> true | |
101 | ssl_context(server, SSL0, M:[close_parent(true)|SSLOptions]), | |
102 | ( http:ssl_server_create_hook(SSL0, SSL1, Options1) | |
103 | -> ensure_close_parent(SSL1, SSL) | |
102 | 104 | ; SSL = SSL0 |
103 | 105 | ), |
104 | 106 | atom_concat('httpsd', Port, Queue), |
108 | 110 | | Options1 |
109 | 111 | ]. |
110 | 112 | |
113 | ensure_close_parent(SSL0, SSL) :- | |
114 | ( ssl_property(SSL0, close_parent(true)) | |
115 | -> SSL = SSL0 | |
116 | ; ssl_set_options(SSL0, SSL, [close_parent(true)]) | |
117 | ). | |
118 | ||
111 | 119 | %! add_secure_ciphers(+SSLOptions0, -SSLOptions) |
112 | 120 | % |
113 | 121 | % Add ciphers from ssl_secure_ciphers/1 if no ciphers are provided. |
153 | 161 | % Implement the accept for HTTPS connections. |
154 | 162 | |
155 | 163 | thread_httpd:accept_hook(Goal, Options) :- |
156 | memberchk(ssl_instance(SSL), Options), | |
164 | memberchk(ssl_instance(SSL0), Options), | |
157 | 165 | !, |
158 | 166 | memberchk(queue(Queue), Options), |
159 | 167 | memberchk(tcp_socket(Socket), Options), |
160 | 168 | tcp_accept(Socket, Client, Peer), |
161 | 169 | debug(http(connection), 'New HTTPS connection from ~p', [Peer]), |
162 | 170 | http_enough_workers(Queue, accept, Peer), |
171 | ensure_close_parent(SSL0, SSL), | |
163 | 172 | thread_send_message(Queue, ssl_client(SSL, Client, Goal, Peer)). |
164 | 173 | |
165 | 174 | %! http:ssl_server_create_hook(+SSL0, -SSL, +Options) is semidet. |
187 | 196 | Goal, In, Out, |
188 | 197 | [peer(Peer), protocol(https)], |
189 | 198 | Options) :- |
190 | ( http:ssl_server_open_client_hook(SSL0, SSL1, Options) | |
199 | ( http:ssl_server_open_client_hook(SSL0, SSL, Options) | |
191 | 200 | -> true |
192 | ; SSL1 = SSL0 | |
201 | ; SSL = SSL0 | |
193 | 202 | ), |
194 | 203 | option(timeout(TMO), Options, 60), |
195 | 204 | tcp_open_socket(Client, Read, Write), |
196 | 205 | set_stream(Read, timeout(TMO)), |
197 | 206 | set_stream(Write, timeout(TMO)), |
198 | ssl_set_options(SSL1, SSL, [close_parent(true)]), | |
199 | 207 | catch(ssl_negotiate(SSL, Read, Write, In, Out), |
200 | 208 | E, |
201 | 209 | ssl_failed(Read, Write, E)). |
223 | 231 | |
224 | 232 | ssl_protocol_hook(Parts, PlainStreamPair, StreamPair, Options) :- |
225 | 233 | memberchk(host(Host), Parts), |
234 | include(ssl_option, Options, SSLOptions), | |
226 | 235 | ssl_context(client, SSL, [ host(Host), |
227 | 236 | close_parent(true) |
228 | | Options | |
237 | | SSLOptions | |
229 | 238 | ]), |
230 | 239 | stream_pair(PlainStreamPair, PlainIn, PlainOut), |
231 | 240 | % if an exception arises, http_open/3 closes the stream for us |
232 | 241 | ssl_negotiate(SSL, PlainIn, PlainOut, In, Out), |
233 | 242 | stream_pair(StreamPair, In, Out). |
234 | 243 | |
244 | % Might be better to be more selective, but passing the options from | |
245 | % http_open/3 with more than 1 argument makes ssl_context/3 fail. | |
246 | ||
247 | ssl_option(Term) :- | |
248 | compound(Term), | |
249 | compound_name_arity(Term, _, 1). | |
235 | 250 | |
236 | 251 | %! http:http_connection_over_proxy(+Proxy, +Parts, +HostPort, -StreamPair, |
237 | 252 | %! +OptionsIn, -OptionsOut) |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | 5 | Copyright (c) 2004-2020, SWI-Prolog Foundation |
6 | 6 | VU University Amsterdam |
7 | CWI, Amsterdam | |
7 | 8 | All rights reserved. |
8 | 9 | |
9 | 10 | Redistribution and use in source and binary forms, with or without |
47 | 48 | ssl_context/3, % +Role, -Config, :Options |
48 | 49 | ssl_add_certificate_key/4, % +Config, +Cert, +Key, -Config |
49 | 50 | ssl_set_options/3, % +Config0, -Config, +Options |
51 | ssl_property/2, % +Config, ?Property | |
50 | 52 | ssl_negotiate/5, % +Config, +PlainRead, +PlainWrite, |
51 | 53 | % -SSLRead, -SSLWrite |
52 | 54 | ssl_peer_certificate/2, % +Stream, -Certificate |
72 | 74 | :- predicate_options(ssl_context/3, 3, |
73 | 75 | [ host(atom), |
74 | 76 | port(integer), |
77 | cacerts(list), | |
75 | 78 | certificate_file(atom), |
76 | 79 | key_file(atom), |
77 | 80 | certificate_key_pairs(any), |
358 | 361 | ssl_copy_context(SSL0, SSL), |
359 | 362 | '_ssl_add_certificate_key'(SSL, Cert, Key). |
360 | 363 | |
361 | ssl_copy_context(SSL0, SSL) :- | |
362 | ssl_context(server, SSL, []), | |
363 | '_ssl_init_from_context'(SSL0, SSL). | |
364 | ||
365 | 364 | %! ssl_set_options(+SSL0, -SSL, +Options) |
366 | 365 | % |
367 | 366 | % SSL is the same as SSL0, except for the options specified in |
377 | 376 | ssl_set_options(SSL0, SSL, Options) :- |
378 | 377 | ssl_copy_context(SSL0, SSL), |
379 | 378 | '_ssl_set_options'(SSL, Options). |
379 | ||
380 | %! ssl_property(+SSL, ?Property) is semidet. | |
381 | % | |
382 | % True when Property is a property of SSL. Defined properties are: | |
383 | % | |
384 | % - close_parent(?Bool) | |
385 | % | |
386 | % @tbd This version is a very minimal implementation of the generic | |
387 | % property interface. Future versions will add more properties and | |
388 | % non-determinism. | |
380 | 389 | |
381 | 390 | %! ssl_negotiate(+SSL, |
382 | 391 | %! +PlainRead, +PlainWrite, |
3 | 3 | Markus Triska and James Cash |
4 | 4 | E-mail: J.Wielemaker@vu.nl |
5 | 5 | WWW: http://www.swi-prolog.org |
6 | Copyright (c) 2004-2018, SWI-Prolog Foundation | |
6 | Copyright (c) 2004-2020, SWI-Prolog Foundation | |
7 | 7 | VU University Amsterdam |
8 | CWI, Amsterdam | |
8 | 9 | All rights reserved. |
9 | 10 | |
10 | 11 | Redistribution and use in source and binary forms, with or without |
144 | 145 | static functor_t FUNCTOR_certificate1; |
145 | 146 | |
146 | 147 | typedef enum |
147 | { PL_SSL_NONE | |
148 | , PL_SSL_SERVER | |
149 | , PL_SSL_CLIENT | |
148 | { PL_SSL_NONE, | |
149 | PL_SSL_SERVER, | |
150 | PL_SSL_CLIENT | |
150 | 151 | } PL_SSL_ROLE; |
151 | 152 | |
152 | 153 | typedef enum |
153 | { SSL_PL_OK | |
154 | , SSL_PL_RETRY | |
155 | , SSL_PL_ERROR | |
154 | { SSL_PL_OK, | |
155 | SSL_PL_RETRY, | |
156 | SSL_PL_ERROR | |
156 | 157 | } SSL_PL_STATUS; |
157 | 158 | |
158 | 159 | #define SSL_CERT_VERIFY_MORE 0 |
167 | 168 | static int ssl_idx; |
168 | 169 | static int ctx_idx; |
169 | 170 | |
170 | typedef struct pl_cert_key_pair { | |
171 | X509 *certificate_X509; | |
172 | char *key; | |
173 | char *certificate; | |
171 | typedef struct pl_cert_key_pair | |
172 | { X509 *certificate_X509; | |
173 | char *key; | |
174 | char *certificate; | |
174 | 175 | } PL_CERT_KEY_PAIR; |
175 | 176 | |
176 | typedef struct pl_ssl_callback { | |
177 | record_t goal; | |
178 | module_t module; | |
177 | typedef struct pl_ssl_callback | |
178 | { record_t goal; | |
179 | module_t module; | |
179 | 180 | } PL_SSL_CALLBACK; |
180 | 181 | |
181 | typedef struct pl_ssl_protocol { | |
182 | BOOL is_set; | |
183 | int version; | |
182 | typedef struct pl_ssl_protocol | |
183 | { BOOL is_set; | |
184 | int version; | |
184 | 185 | } PL_SSL_PROTOCOL; |
185 | 186 | |
186 | typedef struct pl_ssl { | |
187 | long magic; | |
187 | typedef struct | |
188 | { int references; | |
189 | STACK_OF(X509) *cacerts; | |
190 | } cacert_stack; | |
191 | ||
192 | typedef struct pl_ssl | |
193 | { long magic; | |
188 | 194 | /* |
189 | 195 | * Are we server or client |
190 | 196 | */ |
191 | PL_SSL_ROLE role; | |
192 | ||
193 | int close_parent; | |
194 | atom_t atom; | |
195 | BOOL close_notify; | |
196 | ||
197 | /* | |
198 | * Context, Certificate, SSL info | |
199 | */ | |
200 | SSL_CTX *ctx; | |
201 | int idx; | |
202 | X509 *peer_cert; | |
203 | ||
204 | /* | |
205 | * In case of the client the host we're connecting to. | |
206 | */ | |
207 | char *host; | |
208 | ||
209 | /* | |
210 | * Various parameters affecting the SSL layer | |
211 | */ | |
212 | STACK_OF(X509) *cacerts; | |
213 | ||
214 | char *certificate_file; | |
215 | char *key_file; | |
216 | PL_CERT_KEY_PAIR cert_key_pairs[SSL_MAX_CERT_KEY_PAIRS]; | |
217 | int num_cert_key_pairs; | |
218 | ||
219 | char *cipher_list; | |
220 | char *ecdh_curve; | |
221 | STACK_OF(X509_CRL) *crl_list; | |
222 | char *password; | |
223 | BOOL crl_required; | |
224 | BOOL peer_cert_required; | |
225 | ||
226 | PL_SSL_PROTOCOL min_protocol; | |
227 | PL_SSL_PROTOCOL max_protocol; | |
228 | ||
229 | /* | |
230 | * Application defined handlers | |
231 | */ | |
232 | PL_SSL_CALLBACK cb_cert_verify; | |
233 | PL_SSL_CALLBACK cb_pem_passwd; | |
234 | PL_SSL_CALLBACK cb_sni; | |
235 | PL_SSL_CALLBACK cb_alpn_proto; | |
197 | PL_SSL_ROLE role; | |
198 | ||
199 | int close_parent; | |
200 | atom_t atom; | |
201 | BOOL close_notify; | |
202 | ||
203 | /* | |
204 | * Context, Certificate, SSL info | |
205 | */ | |
206 | SSL_CTX *ctx; | |
207 | int idx; | |
208 | X509 *peer_cert; | |
209 | ||
210 | /* | |
211 | * In case of the client the host we're connecting to. | |
212 | */ | |
213 | char *host; | |
214 | ||
215 | /* | |
216 | * Various parameters affecting the SSL layer | |
217 | */ | |
218 | cacert_stack *cacerts; | |
219 | ||
220 | char *certificate_file; | |
221 | char *key_file; | |
222 | PL_CERT_KEY_PAIR cert_key_pairs[SSL_MAX_CERT_KEY_PAIRS]; | |
223 | int num_cert_key_pairs; | |
224 | ||
225 | char *cipher_list; | |
226 | char *ecdh_curve; | |
227 | STACK_OF(X509_CRL) *crl_list; | |
228 | char *password; | |
229 | BOOL crl_required; | |
230 | BOOL peer_cert_required; | |
231 | ||
232 | PL_SSL_PROTOCOL min_protocol; | |
233 | PL_SSL_PROTOCOL max_protocol; | |
234 | ||
235 | /* | |
236 | * Application defined handlers | |
237 | */ | |
238 | PL_SSL_CALLBACK cb_cert_verify; | |
239 | PL_SSL_CALLBACK cb_pem_passwd; | |
240 | PL_SSL_CALLBACK cb_sni; | |
241 | PL_SSL_CALLBACK cb_alpn_proto; | |
236 | 242 | #ifndef HAVE_X509_CHECK_HOST |
237 | int hostname_check_status; | |
238 | #endif | |
239 | unsigned char *alpn_protos; | |
240 | size_t alpn_protos_len; | |
243 | int hostname_check_status; | |
244 | #endif | |
245 | unsigned char *alpn_protos; | |
246 | size_t alpn_protos_len; | |
241 | 247 | } PL_SSL; |
242 | 248 | |
243 | typedef struct ssl_instance { | |
244 | PL_SSL *config; | |
245 | SSL *ssl; | |
246 | IOSTREAM *sread; /* wire streams */ | |
247 | IOSTREAM *swrite; | |
248 | IOSTREAM *dread; /* data streams */ | |
249 | IOSTREAM *dwrite; | |
250 | int close_needed; | |
251 | BOOL fatal_alert; | |
249 | typedef struct ssl_instance | |
250 | { PL_SSL *config; | |
251 | SSL *ssl; | |
252 | IOSTREAM *sread; /* wire streams */ | |
253 | IOSTREAM *swrite; | |
254 | IOSTREAM *dread; /* data streams */ | |
255 | IOSTREAM *dwrite; | |
256 | int close_needed; | |
257 | BOOL fatal_alert; | |
252 | 258 | } PL_SSL_INSTANCE; |
253 | 259 | |
254 | 260 | |
256 | 262 | { RSA_MODE, EVP_MODE |
257 | 263 | } crypt_mode_t; |
258 | 264 | |
265 | ||
266 | /******************************* | |
267 | * ATOMIC * | |
268 | *******************************/ | |
269 | ||
270 | #define ATOMIC_ADD(ptr, v) __atomic_add_fetch(ptr, v, __ATOMIC_SEQ_CST) | |
271 | #define ATOMIC_SUB(ptr, v) __atomic_sub_fetch(ptr, v, __ATOMIC_SEQ_CST) | |
272 | #define ATOMIC_INC(ptr) ATOMIC_ADD(ptr, 1) /* ++(*ptr) */ | |
273 | #define ATOMIC_DEC(ptr) ATOMIC_SUB(ptr, 1) /* --(*ptr) */ | |
274 | #define __COMPARE_AND_SWAP(at, from, to) \ | |
275 | __atomic_compare_exchange_n(at, &(from), to, FALSE, \ | |
276 | __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) | |
277 | ||
278 | static inline int | |
279 | COMPARE_AND_SWAP_PTR(void *at, void *from, void *to) | |
280 | { void **ptr = at; | |
281 | ||
282 | return __COMPARE_AND_SWAP(ptr, from, to); | |
283 | } | |
284 | ||
285 | ||
286 | /******************************* | |
287 | * MANAGE STRUCT VALUES * | |
288 | *******************************/ | |
289 | ||
290 | #define set_string(obj, field, str) \ | |
291 | attr_set_string(&((obj)->field), str) | |
292 | ||
293 | static void | |
294 | attr_set_string(char **where, const char *str) | |
295 | { if ( *where ) | |
296 | free(*where); | |
297 | if ( str ) | |
298 | *where = ssl_strdup(str); | |
299 | } | |
300 | ||
301 | static cacert_stack * | |
302 | new_cacert_stack(void) | |
303 | { cacert_stack *s = malloc(sizeof(*s)); | |
304 | ||
305 | if ( s ) | |
306 | { s->references = 1; | |
307 | if ( !(s->cacerts=sk_X509_new_null()) ) | |
308 | { free(s); | |
309 | s = NULL; | |
310 | } | |
311 | } | |
312 | ||
313 | return s; | |
314 | } | |
315 | ||
316 | static cacert_stack * | |
317 | dup_cacert_stack(cacert_stack *s) | |
318 | { if ( s ) | |
319 | ATOMIC_INC(&s->references); | |
320 | ||
321 | return s; | |
322 | } | |
323 | ||
324 | static void | |
325 | free_cacert_stack(cacert_stack *s) | |
326 | { if ( s && ATOMIC_DEC(&s->references) == 0 ) | |
327 | { sk_X509_pop_free(s->cacerts, X509_free); | |
328 | free(s); | |
329 | } | |
330 | } | |
331 | ||
332 | /******************************* | |
333 | * GET TYPED TERM ARGUMENTS * | |
334 | *******************************/ | |
335 | ||
259 | 336 | static int |
260 | 337 | get_char_arg(int a, term_t t, char **s) |
261 | 338 | { term_t t2 = PL_new_term_ref(); |
262 | 339 | |
263 | 340 | _PL_get_arg(a, t, t2); |
264 | if ( !PL_get_chars(t2, s, CVT_ATOM|CVT_STRING|CVT_EXCEPTION) ) | |
265 | return FALSE; | |
266 | ||
267 | return TRUE; | |
341 | return PL_get_chars(t2, s, CVT_ATOM|CVT_STRING|CVT_EXCEPTION); | |
268 | 342 | } |
269 | 343 | |
270 | 344 | |
273 | 347 | { term_t t2 = PL_new_term_ref(); |
274 | 348 | |
275 | 349 | _PL_get_arg(a, t, t2); |
276 | if ( !PL_get_bool_ex(t2, i) ) | |
277 | return FALSE; | |
278 | ||
279 | return TRUE; | |
350 | return PL_get_bool_ex(t2, i); | |
280 | 351 | } |
281 | 352 | |
282 | 353 | |
285 | 356 | { term_t t2 = PL_new_term_ref(); |
286 | 357 | |
287 | 358 | _PL_get_arg(a, t, t2); |
288 | if ( !PL_get_file_name(t2, f, PL_FILE_EXIST) ) | |
289 | return FALSE; | |
290 | ||
291 | return TRUE; | |
359 | return PL_get_file_name(t2, f, PL_FILE_EXIST); | |
292 | 360 | } |
293 | 361 | |
294 | 362 | |
295 | 363 | static int |
296 | 364 | unify_bignum(term_t t, const BIGNUM *bn) |
297 | { | |
298 | int rc; | |
365 | { int rc; | |
366 | ||
299 | 367 | if ( bn ) |
300 | 368 | { char *hex = BN_bn2hex(bn); |
301 | 369 | |
302 | 370 | rc = PL_unify_chars(t, PL_STRING|REP_ISO_LATIN_1, (size_t)-1, hex); |
303 | 371 | OPENSSL_free(hex); |
304 | 372 | } else |
305 | rc = PL_unify_atom(t, ATOM_minus); | |
373 | { rc = PL_unify_atom(t, ATOM_minus); | |
374 | } | |
306 | 375 | |
307 | 376 | return rc; |
308 | 377 | } |
342 | 411 | |
343 | 412 | if (time->type == V_ASN1_UTCTIME) |
344 | 413 | { if ((length < 11) || (length > 17)) |
345 | { ssl_deb(2, "Unable to parse time - expected either 11 or 17 chars, not %d", length); | |
414 | { ssl_deb(2, "Unable to parse time - expected either 11 or 17 chars," | |
415 | " not %d", length); | |
346 | 416 | return FALSE; |
347 | 417 | } |
348 | 418 | /* Otherwise just get the first 10 chars - ignore seconds */ |
352 | 422 | length -= 10; |
353 | 423 | } else |
354 | 424 | { if (length < 13) |
355 | { ssl_deb(2, "Unable to parse time - expected at least 13 chars, not %d", length); | |
425 | { ssl_deb(2, "Unable to parse time - expected at least 13 chars," | |
426 | " not %d", length); | |
356 | 427 | return FALSE; |
357 | 428 | } |
358 | 429 | /* Otherwise just get the first 12 chars - ignore seconds */ |
379 | 450 | |
380 | 451 | /* If not UTC, calculate offset */ |
381 | 452 | if (*source == 'Z') |
382 | lSecondsFromUTC = 0; | |
383 | else | |
453 | { lSecondsFromUTC = 0; | |
454 | } else | |
384 | 455 | { if ( length < 6 || (*source != '+' && source[5] != '-') ) |
385 | 456 | { ssl_deb(2, "Unable to parse time. Missing UTC offset"); |
386 | 457 | return FALSE; |
401 | 472 | time_tm.tm_year += 100; /* according to RFC 2459 */ |
402 | 473 | time_tm.tm_wday = 0; |
403 | 474 | time_tm.tm_yday = 0; |
404 | time_tm.tm_isdst = 0; /* No DST adjustment requested, though mktime might do it anyway */ | |
475 | time_tm.tm_isdst = 0; /* No DST adjustment requested, though */ | |
476 | /* mktime might do it anyway */ | |
405 | 477 | |
406 | 478 | #ifdef HAVE_TIMEGM |
407 | 479 | result = timegm(&time_tm); |
413 | 485 | } |
414 | 486 | #else |
415 | 487 | result = mktime(&time_tm); |
416 | /* mktime assumes that the time_tm contains information for localtime. Convert back to UTC: */ | |
488 | /* mktime assumes that the time_tm contains information for localtime. */ | |
489 | /* Convert back to UTC: */ | |
417 | 490 | if ((time_t)-1 != result) |
418 | 491 | { result += lSecondsFromUTC; /* Add in the UTC offset of the original value */ |
419 | 492 | result -= timezone; /* Adjust for localtime */ |
429 | 502 | static const EVP_MD * |
430 | 503 | algorithm_to_type(const ASN1_OBJECT* algorithm, int *nid) |
431 | 504 | { *nid = OBJ_obj2nid(algorithm); |
432 | /* Annoyingly, EVP_get_digestbynid doesnt work for some of these algorithms. Instead check for | |
433 | them explicitly and set the digest manually | |
505 | /* Annoyingly, EVP_get_digestbynid doesnt work for some of these | |
506 | algorithms. Instead check for them explicitly and set the digest manually | |
434 | 507 | */ |
435 | 508 | switch (*nid) |
436 | 509 | { case NID_ecdsa_with_SHA1: |
451 | 524 | #if defined(HAVE_X509_DIGEST) && defined(HAVE_X509_CRL_DIGEST) |
452 | 525 | |
453 | 526 | static int |
454 | hash_X509_digest_wrapper(const void *data, const EVP_MD *type, unsigned char* md, unsigned int *l) | |
455 | { | |
456 | return X509_digest((X509 *) data, type, md, l); | |
457 | } | |
458 | ||
459 | static int | |
460 | hash_X509_crl_digest_wrapper(const void *data, const EVP_MD *type, unsigned char* md, unsigned int *l) | |
461 | { | |
462 | return X509_CRL_digest((X509_CRL *) data, type, md, l); | |
527 | hash_X509_digest_wrapper(const void *data, const EVP_MD *type, | |
528 | unsigned char* md, unsigned int *l) | |
529 | { return X509_digest((X509 *) data, type, md, l); | |
530 | } | |
531 | ||
532 | static int | |
533 | hash_X509_crl_digest_wrapper(const void *data, const EVP_MD *type, | |
534 | unsigned char* md, unsigned int *l) | |
535 | { return X509_CRL_digest((X509_CRL *) data, type, md, l); | |
463 | 536 | } |
464 | 537 | |
465 | 538 | static int |
466 | 539 | unify_hash(term_t hash, const ASN1_OBJECT* algorithm, |
467 | int (*data_to_digest)(const void*, const EVP_MD *, unsigned char*, unsigned int*), | |
540 | int (*data_to_digest)(const void*, const EVP_MD *, | |
541 | unsigned char*, unsigned int*), | |
468 | 542 | void *data) |
469 | { | |
470 | int nid; | |
543 | { int nid; | |
471 | 544 | const EVP_MD *type = algorithm_to_type(algorithm, &nid); |
472 | 545 | unsigned char digest[EVP_MAX_MD_SIZE]; |
473 | 546 | unsigned int digest_length; |
474 | 547 | |
475 | if (type == NULL) | |
548 | if ( type == NULL ) | |
476 | 549 | return PL_unify_term(hash, |
477 | 550 | PL_FUNCTOR, FUNCTOR_unsupported_hash_algorithm1, |
478 | 551 | PL_INT, nid); |
479 | 552 | |
480 | if (!data_to_digest(data, type, digest, &digest_length)) | |
553 | if ( !data_to_digest(data, type, digest, &digest_length) ) | |
481 | 554 | return FALSE; |
482 | 555 | |
483 | 556 | return unify_bytes_hex(hash, digest_length, digest); |
485 | 558 | |
486 | 559 | #else |
487 | 560 | |
488 | static int i2d_X509_CRL_INFO_wrapper(void* i, unsigned char** d) | |
489 | { | |
490 | return i2d_X509_CRL_INFO(i, d); | |
491 | } | |
492 | ||
493 | static int i2d_X509_CINF_wrapper(void* i, unsigned char** d) | |
494 | { | |
495 | return i2d_X509_CINF(i, d); | |
561 | static int | |
562 | i2d_X509_CRL_INFO_wrapper(void* i, unsigned char** d) | |
563 | { return i2d_X509_CRL_INFO(i, d); | |
564 | } | |
565 | ||
566 | static int | |
567 | i2d_X509_CINF_wrapper(void* i, unsigned char** d) | |
568 | { return i2d_X509_CINF(i, d); | |
496 | 569 | } |
497 | 570 | |
498 | 571 | |
509 | 582 | unsigned char* p; |
510 | 583 | /* Generate hash */ |
511 | 584 | |
512 | if (type == NULL) | |
585 | if ( type == NULL ) | |
513 | 586 | return PL_unify_term(hash, |
514 | 587 | PL_FUNCTOR, FUNCTOR_unsupported_hash_algorithm1, |
515 | 588 | PL_INT, nid); |
516 | 589 | |
517 | 590 | digestible_length=i2d(data,NULL); |
518 | 591 | digest_buffer = PL_malloc(digestible_length); |
519 | if (digest_buffer == NULL) | |
592 | if ( digest_buffer == NULL ) | |
520 | 593 | return PL_resource_error("memory"); |
521 | 594 | |
522 | 595 | /* i2d_X509_CINF will change the value of p. We need to pass in a copy */ |
551 | 624 | term_t list = PL_copy_term_ref(term); |
552 | 625 | term_t item = PL_new_term_ref(); |
553 | 626 | |
554 | if (name == NULL) | |
555 | return PL_unify_term(term, | |
556 | PL_CHARS, "<null>"); | |
627 | if ( name == NULL ) | |
628 | return PL_unify_term(term, PL_CHARS, "<null>"); | |
629 | ||
557 | 630 | for (ni = 0; ni < X509_NAME_entry_count(name); ni++) |
558 | 631 | { X509_NAME_ENTRY* e = X509_NAME_get_entry(name, ni); |
559 | 632 | ASN1_STRING* entry_data = X509_NAME_ENTRY_get_data(e); |
564 | 637 | return PL_resource_error("memory"); |
565 | 638 | |
566 | 639 | rc = ( PL_unify_list(list, item, list) && |
567 | PL_unify_term(item, | |
568 | PL_FUNCTOR, FUNCTOR_equals2, | |
569 | PL_CHARS, OBJ_nid2sn(OBJ_obj2nid(X509_NAME_ENTRY_get_object(e))), | |
570 | PL_UTF8_CHARS, utf8_data) | |
640 | PL_unify_term( | |
641 | item, | |
642 | PL_FUNCTOR, FUNCTOR_equals2, | |
643 | PL_CHARS, OBJ_nid2sn(OBJ_obj2nid(X509_NAME_ENTRY_get_object(e))), | |
644 | PL_UTF8_CHARS, utf8_data) | |
571 | 645 | ); |
572 | 646 | OPENSSL_free(utf8_data); |
573 | 647 | if ( !rc ) |
574 | 648 | return FALSE; |
575 | 649 | } |
650 | ||
576 | 651 | return PL_unify_nil(list); |
577 | 652 | } |
578 | 653 | |
584 | 659 | #ifndef HAVE_X509_CRL_GET0_SIGNATURE |
585 | 660 | /* Avoid conflict if the prototype is there, but the function is not */ |
586 | 661 | #define X509_CRL_get0_signature my_X509_CRL_get0_signature |
662 | ||
587 | 663 | static void |
588 | X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, const X509_ALGOR **palg) | |
589 | { | |
590 | *psig = crl->signature; | |
664 | X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, | |
665 | const X509_ALGOR **palg) | |
666 | { *psig = crl->signature; | |
591 | 667 | *palg = crl->sig_alg; |
592 | 668 | } |
593 | 669 | #endif |
595 | 671 | #ifndef HAVE_X509_GET0_SIGNATURE |
596 | 672 | /* Avoid conflict if the prototype is there, but the function is not */ |
597 | 673 | #define X509_get0_signature my_X509_get0_signature |
674 | ||
598 | 675 | static void |
599 | X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg, const X509 *data) | |
676 | X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg, | |
677 | const X509 *data) | |
600 | 678 | { |
601 | 679 | *psig = data->signature; |
602 | 680 | *palg = data->sig_alg; |
606 | 684 | |
607 | 685 | static int |
608 | 686 | unify_crl(term_t term, X509_CRL* crl) |
609 | { | |
610 | const ASN1_BIT_STRING *psig; | |
687 | { const ASN1_BIT_STRING *psig; | |
611 | 688 | const X509_ALGOR *palg; |
612 | 689 | STACK_OF(X509_REVOKED) *revoked = X509_CRL_get_REVOKED(crl); |
613 | 690 | int i; |
633 | 710 | i2a_ASN1_INTEGER(mem, (ASN1_BIT_STRING *) psig); |
634 | 711 | if (!(unify_name(issuer, X509_CRL_get_issuer(crl)) && |
635 | 712 | #ifdef HAVE_X509_CRL_DIGEST |
636 | unify_hash(hash, palg->algorithm, hash_X509_crl_digest_wrapper, crl) && | |
713 | unify_hash(hash, palg->algorithm, hash_X509_crl_digest_wrapper, crl) && | |
637 | 714 | #else |
638 | 715 | unify_hash(hash, palg->algorithm, i2d_X509_CRL_INFO_wrapper, crl->crl) && |
639 | 716 | #endif |
651 | 728 | PL_TERM, next_update, |
652 | 729 | PL_FUNCTOR, FUNCTOR_revocations1, |
653 | 730 | PL_TERM, revocations))) |
654 | { | |
655 | return FALSE; | |
656 | } | |
731 | { return FALSE; | |
732 | } | |
733 | ||
657 | 734 | for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) |
658 | { X509_REVOKED *r = sk_X509_REVOKED_value(revoked, i); | |
659 | (void)BIO_reset(mem); | |
660 | i2a_ASN1_INTEGER(mem, X509_REVOKED_get0_serialNumber(r)); | |
661 | result &= (((n = BIO_get_mem_data(mem, &p)) > 0) && | |
662 | PL_unify_list(list, item, list) && | |
663 | (revocation_date = PL_new_term_ref()) && | |
664 | unify_asn1_time(revocation_date, X509_REVOKED_get0_revocationDate(r)) && | |
665 | PL_unify_term(item, | |
666 | PL_FUNCTOR, FUNCTOR_revoked2, | |
667 | PL_NCHARS, (size_t)n, p, | |
668 | PL_TERM, revocation_date)); | |
669 | if (BIO_reset(mem) != 1) | |
670 | { | |
671 | BIO_free(mem); | |
672 | // The only reason I can imagine this would fail is out of memory | |
673 | return PL_resource_error("memory"); | |
674 | } | |
675 | } | |
735 | { X509_REVOKED *r = sk_X509_REVOKED_value(revoked, i); | |
736 | ||
737 | (void)BIO_reset(mem); | |
738 | i2a_ASN1_INTEGER(mem, X509_REVOKED_get0_serialNumber(r)); | |
739 | result &= (((n = BIO_get_mem_data(mem, &p)) > 0) && | |
740 | PL_unify_list(list, item, list) && | |
741 | (revocation_date = PL_new_term_ref()) && | |
742 | unify_asn1_time(revocation_date, X509_REVOKED_get0_revocationDate(r)) && | |
743 | PL_unify_term(item, | |
744 | PL_FUNCTOR, FUNCTOR_revoked2, | |
745 | PL_NCHARS, (size_t)n, p, | |
746 | PL_TERM, revocation_date)); | |
747 | if ( BIO_reset(mem) != 1 ) | |
748 | { BIO_free(mem); | |
749 | // The only reason I can imagine this would fail is out of memory | |
750 | return PL_resource_error("memory"); | |
751 | } | |
752 | } | |
753 | ||
676 | 754 | BIO_free(mem); |
677 | 755 | return result && PL_unify_nil(list); |
678 | 756 | } |
715 | 793 | #ifndef OPENSSL_NO_EC |
716 | 794 | static int |
717 | 795 | unify_ec(term_t item, EC_KEY *key) |
718 | { | |
719 | unsigned char *buf = NULL; | |
796 | { unsigned char *buf = NULL; | |
720 | 797 | int rc, publen; |
721 | 798 | term_t privkey, pubkey; |
722 | 799 | |
1231 | 1308 | { GET0SIG_CONST_T ASN1_BIT_STRING *psig; |
1232 | 1309 | GET0SIG_CONST_T X509_ALGOR *palg; |
1233 | 1310 | const char *salgorithm; |
1234 | ||
1311 | ||
1235 | 1312 | X509_get0_signature(&psig, &palg, cert); |
1236 | 1313 | if ((salgorithm = OBJ_nid2sn(OBJ_obj2nid(palg->algorithm))) != NULL) |
1237 | 1314 | { return PL_unify_chars(Field, PL_ATOM|REP_UTF8, strlen(salgorithm), salgorithm); |
1243 | 1320 | fetch_hash(term_t Field, X509* cert) |
1244 | 1321 | { GET0SIG_CONST_T ASN1_BIT_STRING *psig; |
1245 | 1322 | GET0SIG_CONST_T X509_ALGOR *palg; |
1246 | ||
1323 | ||
1247 | 1324 | X509_get0_signature(&psig, &palg, cert); |
1248 | 1325 | #ifdef HAVE_X509_DIGEST |
1249 | 1326 | return unify_hash(Field, palg->algorithm, hash_X509_digest_wrapper, cert); |
1284 | 1361 | {"signature", fetch_signature}, |
1285 | 1362 | {"signature_algorithm", fetch_signature_algorithm}, |
1286 | 1363 | {"hash", fetch_hash}, |
1287 | #ifdef HAVE_I2D_RE_X509_TBS | |
1364 | #ifdef HAVE_I2D_RE_X509_TBS | |
1288 | 1365 | {"to_be_signed", fetch_to_be_signed}, |
1289 | 1366 | #endif |
1290 | 1367 | {NULL, NULL}}; |
1885 | 1962 | assert(config->magic == SSL_CONFIG_MAGIC); |
1886 | 1963 | config->magic = 0; |
1887 | 1964 | free(config->host); |
1888 | if (config->cacerts) | |
1889 | sk_X509_pop_free(config->cacerts, X509_free); | |
1965 | free_cacert_stack(config->cacerts); | |
1890 | 1966 | free(config->certificate_file); |
1891 | 1967 | free(config->key_file); |
1892 | 1968 | free(config->cipher_list); |
1952 | 2028 | } |
1953 | 2029 | |
1954 | 2030 | static int |
1955 | ssl_config_dup ( CRYPTO_EX_DATA * to | |
1956 | , | |
2031 | ssl_config_dup(CRYPTO_EX_DATA *to, | |
1957 | 2032 | #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) |
1958 | CRYPTO_EX_DATA * from | |
2033 | CRYPTO_EX_DATA *from, | |
1959 | 2034 | #else |
1960 | const CRYPTO_EX_DATA * from | |
1961 | #endif | |
1962 | , void * pl_ssl | |
1963 | , int parent_ctx_idx | |
1964 | , long argl | |
1965 | , void *argp | |
1966 | ) | |
1967 | { | |
1968 | return 1; | |
2035 | const CRYPTO_EX_DATA *from, | |
2036 | #endif | |
2037 | void *pl_ssl, | |
2038 | int parent_ctx_idx, | |
2039 | long argl, | |
2040 | void *argp) | |
2041 | { return 1; | |
1969 | 2042 | } |
1970 | 2043 | |
1971 | 2044 | static void |
1972 | ssl_config_free( void * ctx | |
1973 | , void * pl_ssl | |
1974 | , CRYPTO_EX_DATA * parent_ctx | |
1975 | , int parent_ctx_idx | |
1976 | , long argl | |
1977 | , void *argp | |
1978 | ) | |
1979 | { | |
1980 | PL_SSL *config = NULL; | |
1981 | ||
1982 | ssl_deb(1, "calling ssl_config_free()\n"); | |
1983 | if ((config = SSL_CTX_get_ex_data(ctx, ctx_idx)) != NULL) { | |
1984 | assert(config->magic == SSL_CONFIG_MAGIC); | |
1985 | ssl_free(config); | |
1986 | } | |
1987 | } | |
1988 | ||
1989 | ||
1990 | static int | |
1991 | ssl_cb_cert_verify(int preverify_ok, X509_STORE_CTX *ctx) | |
2045 | ssl_config_free(void *ctx, | |
2046 | void *pl_ssl, | |
2047 | CRYPTO_EX_DATA *parent_ctx, | |
2048 | int parent_ctx_idx, | |
2049 | long argl, | |
2050 | void *argp) | |
2051 | { PL_SSL *config = NULL; | |
2052 | ||
2053 | ssl_deb(1, "calling ssl_config_free()\n"); | |
2054 | if ( (config=SSL_CTX_get_ex_data(ctx, ctx_idx))) | |
2055 | { assert(config->magic == SSL_CONFIG_MAGIC); | |
2056 | ssl_free(config); | |
2057 | } | |
2058 | } | |
2059 | ||
2060 | ||
1992 | 2061 | /* |
1993 | 2062 | * Function handling certificate verification |
1994 | 2063 | */ |
1995 | { | |
1996 | SSL * ssl = NULL; | |
1997 | PL_SSL * config = NULL; | |
1998 | /* | |
1999 | * Get our config data | |
2000 | */ | |
2001 | ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); | |
2002 | config = SSL_get_ex_data(ssl, ssl_idx); | |
2003 | ||
2004 | ||
2005 | ||
2006 | ssl_deb(1, " ---- INIT Handling certificate verification\n"); | |
2007 | ssl_deb(1, " Certificate preverified %sok\n", | |
2008 | preverify_ok ? "" : "NOT "); | |
2064 | ||
2065 | static int | |
2066 | ssl_cb_cert_verify(int preverify_ok, X509_STORE_CTX *ctx) | |
2067 | { SSL *ssl = NULL; | |
2068 | PL_SSL *config = NULL; | |
2069 | /* | |
2070 | * Get our config data | |
2071 | */ | |
2072 | ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); | |
2073 | config = SSL_get_ex_data(ssl, ssl_idx); | |
2074 | ||
2075 | ssl_deb(1, " ---- INIT Handling certificate verification\n"); | |
2076 | ssl_deb(1, " Certificate preverified %sok\n", preverify_ok ? "" : "NOT "); | |
2009 | 2077 | #ifndef HAVE_X509_CHECK_HOST |
2010 | 2078 | /* If OpenSSL does not have X509_check_host() then the hostname has not yet been verified. |
2011 | 2079 | Note that we only want to check the hostname of the FIRST certificate. There appears to be no easy way of |
2203 | 2271 | return preverify_ok; |
2204 | 2272 | } |
2205 | 2273 | |
2206 | static int | |
2207 | ssl_cb_pem_passwd(char *buf, int size, int rwflag, void *userdata) | |
2208 | 2274 | /* |
2209 | 2275 | * We're called since the OpenSSL library needs a password to access |
2210 | 2276 | * the private key. The method to require the password is defined in |
2212 | 2278 | * Fill the supplied buffer with the password and return its length |
2213 | 2279 | * or 0 on failure. |
2214 | 2280 | */ |
2215 | { | |
2216 | PL_SSL *config = (PL_SSL *) userdata; | |
2217 | char *passwd = NULL; | |
2218 | int len = 0; | |
2219 | ||
2220 | if (config->cb_pem_passwd.goal) { | |
2221 | /* | |
2222 | * Callback installed | |
2223 | */ | |
2224 | passwd = pl_pem_passwd_hook(config, buf, size); | |
2225 | } else | |
2226 | if (config->password) { | |
2227 | /* | |
2228 | * Password defined | |
2229 | */ | |
2230 | passwd = config->password; | |
2231 | } | |
2232 | ||
2233 | if (passwd) { | |
2234 | if ((len = (int)strlen(passwd)) < size) { | |
2235 | strcpy(buf, passwd); | |
2236 | } else { | |
2237 | len = 0; | |
2238 | } | |
2239 | } | |
2240 | ||
2241 | return len; | |
2281 | ||
2282 | static int | |
2283 | ssl_cb_pem_passwd(char *buf, int size, int rwflag, void *userdata) | |
2284 | { PL_SSL *config = userdata; | |
2285 | char *passwd = NULL; | |
2286 | int len = 0; | |
2287 | ||
2288 | if ( config->cb_pem_passwd.goal ) | |
2289 | { passwd = pl_pem_passwd_hook(config, buf, size); | |
2290 | } else if (config->password) | |
2291 | { passwd = config->password; | |
2292 | } | |
2293 | ||
2294 | if ( passwd ) | |
2295 | { if ( (len = (int)strlen(passwd)) < size ) | |
2296 | strcpy(buf, passwd); | |
2297 | else | |
2298 | len = 0; | |
2299 | } | |
2300 | ||
2301 | return len; | |
2242 | 2302 | } |
2243 | 2303 | |
2244 | 2304 | |
2245 | 2305 | #ifndef OPENSSL_NO_TLSEXT |
2246 | 2306 | static int |
2247 | 2307 | ssl_cb_sni(SSL *s, int *ad, void *arg) |
2248 | { | |
2249 | PL_SSL *config = (PL_SSL *) arg, | |
2250 | *new_config = NULL; | |
2308 | { PL_SSL *config = arg; | |
2309 | PL_SSL *new_config = NULL; | |
2251 | 2310 | const char *servername; |
2252 | 2311 | |
2253 | if ( (servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name)) != NULL ) | |
2312 | if ( (servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name)) ) | |
2254 | 2313 | new_config = pl_sni_hook(config, servername); |
2255 | 2314 | |
2256 | 2315 | if ( new_config == NULL && |
2333 | 2392 | { char errmsg[1024]; |
2334 | 2393 | |
2335 | 2394 | ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg)); |
2336 | ||
2337 | 2395 | Sdprintf("%s\n", errmsg); |
2338 | 2396 | } |
2339 | 2397 | |
2340 | 2398 | |
2341 | static PL_SSL * | |
2342 | ssl_init(PL_SSL_ROLE role, const SSL_METHOD *ssl_method) | |
2343 | 2399 | /* |
2344 | 2400 | * Allocate the holder for our parameters which will specify the |
2345 | 2401 | * configuration parameters and any other statefull parameter. |
2347 | 2403 | * Define method for SSL layer depending on whether we're server or client. |
2348 | 2404 | * Create SSL context. |
2349 | 2405 | */ |
2350 | { | |
2351 | PL_SSL * config = NULL; | |
2352 | SSL_CTX *ssl_ctx = NULL; | |
2353 | ||
2354 | ssl_ctx = SSL_CTX_new(ssl_method); | |
2355 | if (!ssl_ctx) { | |
2356 | ERR_print_errors_pl(); | |
2357 | } else { | |
2358 | long ctx_mode = 0L; | |
2359 | ||
2360 | if ((config = SSL_CTX_get_ex_data(ssl_ctx, ctx_idx)) == NULL) { | |
2361 | ssl_err("Cannot read back application data\n"); | |
2362 | SSL_CTX_free(ssl_ctx); | |
2363 | return NULL; | |
2364 | } | |
2365 | assert(config->magic == SSL_CONFIG_MAGIC); | |
2366 | config->ctx = ssl_ctx; | |
2367 | config->role = role; | |
2368 | config->peer_cert_required = (role != PL_SSL_SERVER); | |
2369 | ||
2370 | /* | |
2371 | * Set SSL_{read,write} behaviour when a renegotiation takes place | |
2372 | * in a blocking transport layer. | |
2373 | */ | |
2374 | ctx_mode = SSL_CTX_get_mode(ssl_ctx); | |
2375 | ctx_mode |= SSL_MODE_AUTO_RETRY; | |
2376 | ctx_mode = SSL_CTX_set_mode(ssl_ctx, ctx_mode); | |
2406 | ||
2407 | static PL_SSL * | |
2408 | ssl_init(PL_SSL_ROLE role, const SSL_METHOD *ssl_method) | |
2409 | { PL_SSL *config = NULL; | |
2410 | SSL_CTX *ssl_ctx = NULL; | |
2411 | ||
2412 | ssl_ctx = SSL_CTX_new(ssl_method); | |
2413 | if ( !ssl_ctx ) | |
2414 | { ERR_print_errors_pl(); | |
2415 | } else | |
2416 | { long ctx_mode = 0L; | |
2417 | ||
2418 | if ( !(config=SSL_CTX_get_ex_data(ssl_ctx, ctx_idx)) ) | |
2419 | { ssl_err("Cannot read back application data\n"); | |
2420 | SSL_CTX_free(ssl_ctx); | |
2421 | return NULL; | |
2377 | 2422 | } |
2378 | 2423 | |
2379 | ssl_deb(1, "Initialized\n"); | |
2380 | ||
2381 | return config; | |
2424 | assert(config->magic == SSL_CONFIG_MAGIC); | |
2425 | config->ctx = ssl_ctx; | |
2426 | config->role = role; | |
2427 | config->peer_cert_required = (role != PL_SSL_SERVER); | |
2428 | ||
2429 | /* | |
2430 | * Set SSL_{read,write} behaviour when a renegotiation takes place | |
2431 | * in a blocking transport layer. | |
2432 | */ | |
2433 | ctx_mode = SSL_CTX_get_mode(ssl_ctx); | |
2434 | ctx_mode |= SSL_MODE_AUTO_RETRY; | |
2435 | ctx_mode = SSL_CTX_set_mode(ssl_ctx, ctx_mode); | |
2436 | } | |
2437 | ||
2438 | ssl_deb(1, "Initialized\n"); | |
2439 | ||
2440 | return config; | |
2382 | 2441 | } |
2383 | 2442 | |
2384 | 2443 | |
2484 | 2543 | const unsigned char *der; |
2485 | 2544 | unsigned long cert_data_length; |
2486 | 2545 | X509 *x509 = NULL; |
2487 | ||
2546 | ||
2488 | 2547 | cert_data = SecCertificateCopyData((SecCertificateRef)cert); |
2489 | 2548 | der = CFDataGetBytePtr(cert_data); |
2490 | 2549 | cert_data_length = CFDataGetLength(cert_data); |
2551 | 2610 | ssl_init_verify_locations(PL_SSL *config) |
2552 | 2611 | { if ( config->cacerts ) |
2553 | 2612 | { X509_STORE *store = X509_STORE_new(); |
2613 | ||
2554 | 2614 | if ( store ) |
2555 | 2615 | { int index = 0; |
2556 | while (index < sk_X509_num(config->cacerts)) | |
2557 | { X509_STORE_add_cert(store, sk_X509_value(config->cacerts, index++)); | |
2616 | STACK_OF(X509) *cacerts = config->cacerts->cacerts; | |
2617 | ||
2618 | while( index < sk_X509_num(cacerts) ) | |
2619 | { X509_STORE_add_cert(store, sk_X509_value(cacerts, index++)); | |
2558 | 2620 | } |
2559 | 2621 | SSL_CTX_set_cert_store(config->ctx, store); |
2560 | 2622 | } |
2561 | ssl_deb(1, "certificate authority(s) installed from individual certificates\n"); | |
2562 | } | |
2623 | ssl_deb(1, "certificate authority(s) installed from certificates\n"); | |
2624 | } | |
2625 | ||
2563 | 2626 | if ( config->crl_list ) |
2564 | 2627 | { X509_STORE *store = SSL_CTX_get_cert_store(config->ctx); |
2565 | 2628 | int i = 0; |
2629 | ||
2566 | 2630 | while (i < sk_X509_CRL_num(config->crl_list)) |
2567 | 2631 | { X509_STORE_add_crl(store, sk_X509_CRL_value(config->crl_list, i)); |
2568 | /* | |
2569 | Sdprintf("Added a CRL...\n"); | |
2570 | BIO * bio = BIO_new_fp(stdout, BIO_NOCLOSE); | |
2571 | X509_CRL_print(bio, sk_X509_CRL_value(config->crl_list, i)); | |
2572 | BIO_free(bio); | |
2573 | */ | |
2574 | 2632 | i++; |
2575 | 2633 | } |
2576 | 2634 | } |
2577 | ||
2578 | 2635 | } |
2579 | 2636 | |
2580 | 2637 | /* The following keys were generated with: |
3227 | 3284 | { atom_t name; |
3228 | 3285 | size_t arity; |
3229 | 3286 | |
3230 | if ( !PL_get_name_arity(head, &name, &arity) ) | |
3287 | if ( !(PL_get_name_arity(head, &name, &arity) && arity == 1) ) | |
3231 | 3288 | return PL_type_error("ssl_option", head); |
3232 | 3289 | |
3233 | if ( name == ATOM_cipher_list && arity == 1 ) | |
3290 | if ( name == ATOM_cipher_list ) | |
3234 | 3291 | { char *s; |
3235 | 3292 | |
3236 | 3293 | if ( !get_char_arg(1, head, &s) ) |
3237 | 3294 | return FALSE; |
3238 | 3295 | |
3239 | if (conf->cipher_list) free(conf->cipher_list); | |
3240 | conf->cipher_list = ssl_strdup(s); | |
3241 | } else if ( name == ATOM_ecdh_curve && arity == 1 ) | |
3296 | set_string(conf, cipher_list, s); | |
3297 | } else if ( name == ATOM_ecdh_curve ) | |
3242 | 3298 | { char *s; |
3243 | 3299 | |
3244 | 3300 | if ( !get_char_arg(1, head, &s) ) |
3245 | 3301 | return FALSE; |
3246 | 3302 | |
3247 | if (conf->ecdh_curve) free(conf->ecdh_curve); | |
3248 | conf->ecdh_curve = ssl_strdup(s); | |
3249 | } else if ( name == ATOM_host && arity == 1 ) | |
3303 | set_string(conf, ecdh_curve, s); | |
3304 | } else if ( name == ATOM_host ) | |
3250 | 3305 | { char *s; |
3251 | 3306 | |
3252 | 3307 | if ( !get_char_arg(1, head, &s) ) |
3253 | 3308 | return FALSE; |
3254 | 3309 | |
3255 | if (conf->host) free(conf->host); | |
3256 | conf->host = ssl_strdup(s); | |
3257 | } else if ( name == ATOM_peer_cert && arity == 1 ) | |
3310 | set_string(conf, host, s); | |
3311 | } else if ( name == ATOM_peer_cert ) | |
3258 | 3312 | { int val; |
3259 | 3313 | |
3260 | 3314 | if ( !get_bool_arg(1, head, &val) ) |
3261 | 3315 | return FALSE; |
3262 | 3316 | |
3263 | 3317 | conf->peer_cert_required = val; |
3264 | } else if ( name == ATOM_cert_verify_hook && arity == 1 ) | |
3318 | } else if ( name == ATOM_cert_verify_hook ) | |
3265 | 3319 | { term_t cb = PL_new_term_ref(); |
3266 | 3320 | _PL_get_arg(1, head, cb); |
3267 | 3321 | |
3270 | 3324 | |
3271 | 3325 | conf->cb_cert_verify.goal = PL_record(cb); |
3272 | 3326 | conf->cb_cert_verify.module = module; |
3273 | } else if ( name == ATOM_close_parent && arity == 1 ) | |
3327 | } else if ( name == ATOM_close_parent ) | |
3274 | 3328 | { int val; |
3275 | 3329 | |
3276 | 3330 | if ( !get_bool_arg(1, head, &val) ) |
3277 | 3331 | return FALSE; |
3278 | 3332 | |
3279 | 3333 | conf->close_parent = val; |
3280 | } else if ( name == ATOM_disable_ssl_methods && arity == 1 ) | |
3334 | } else if ( name == ATOM_disable_ssl_methods ) | |
3281 | 3335 | { term_t opt_head = PL_new_term_ref(); |
3282 | 3336 | term_t opt_tail = PL_new_term_ref(); |
3283 | 3337 | long options = 0; |
3312 | 3366 | |
3313 | 3367 | if ( (isset=(SSL_CTX_set_options(conf->ctx, options)&options)) != options ) |
3314 | 3368 | ssl_deb(1, "SSL_CTX_set_options 0x%lx only set 0x%lx\n", options, isset); |
3315 | } else if ( name == ATOM_min_protocol_version && arity == 1 ) | |
3369 | } else if ( name == ATOM_min_protocol_version ) | |
3316 | 3370 | { term_t val = PL_new_term_ref(); |
3317 | 3371 | int version; |
3318 | 3372 | |
3322 | 3376 | return FALSE; |
3323 | 3377 | conf->min_protocol.is_set = TRUE; |
3324 | 3378 | conf->min_protocol.version = version; |
3325 | } else if ( name == ATOM_max_protocol_version && arity == 1 ) | |
3379 | } else if ( name == ATOM_max_protocol_version ) | |
3326 | 3380 | { term_t val = PL_new_term_ref(); |
3327 | 3381 | int version; |
3328 | 3382 | |
3342 | 3396 | |
3343 | 3397 | conf->cb_sni.goal = PL_record(cb); |
3344 | 3398 | conf->cb_sni.module = module; |
3345 | } else if ( name == ATOM_close_notify && arity == 1 ) | |
3399 | } else if ( name == ATOM_close_notify ) | |
3346 | 3400 | { int val; |
3347 | 3401 | |
3348 | 3402 | if ( !get_bool_arg(1, head, &val) ) |
3349 | 3403 | return FALSE; |
3350 | 3404 | |
3351 | 3405 | conf->close_notify = val; |
3352 | } else if ( name == ATOM_alpn_protocols && arity == 1 ) | |
3406 | } else if ( name == ATOM_alpn_protocols ) | |
3353 | 3407 | { term_t protos_tail = PL_new_term_ref(); |
3354 | 3408 | term_t protos_head = PL_new_term_ref(); |
3355 | 3409 | _PL_get_arg(1, head, protos_tail); |
3380 | 3434 | } |
3381 | 3435 | conf->alpn_protos = protos_vec; |
3382 | 3436 | conf->alpn_protos_len = current_size; |
3383 | } else if ( name == ATOM_alpn_protocol_hook && arity == 1 && | |
3437 | } else if ( name == ATOM_alpn_protocol_hook && | |
3384 | 3438 | conf->role == PL_SSL_SERVER ) |
3385 | 3439 | { term_t cb = PL_new_term_ref(); |
3386 | 3440 | _PL_get_arg(1, head, cb); |
3411 | 3465 | set_malleable_options(conf); |
3412 | 3466 | } |
3413 | 3467 | |
3468 | ||
3469 | static foreign_t | |
3470 | pl_ssl_property(term_t config, term_t prop) | |
3471 | { PL_SSL *conf; | |
3472 | atom_t name; | |
3473 | size_t arity; | |
3474 | ||
3475 | if ( !get_conf(config, &conf) ) | |
3476 | return FALSE; | |
3477 | ||
3478 | if ( PL_get_name_arity(prop, &name, &arity) && arity == 1 ) | |
3479 | { term_t arg = PL_new_term_ref(); | |
3480 | ||
3481 | _PL_get_arg(1, prop, arg); | |
3482 | if ( name == ATOM_close_parent ) | |
3483 | return PL_unify_bool(arg, conf->close_parent); | |
3484 | ||
3485 | return FALSE; | |
3486 | } | |
3487 | ||
3488 | return PL_type_error("ssl_property", prop); | |
3489 | } | |
3490 | ||
3491 | ||
3492 | static const SSL_METHOD * | |
3493 | get_ssl_method(term_t method) | |
3494 | { const SSL_METHOD *ssl_method = NULL; | |
3495 | #if OPENSSL_VERSION_NUMBER < 0x10100000L | |
3496 | atom_t method_name; | |
3497 | #endif | |
3498 | ||
3499 | #if OPENSSL_VERSION_NUMBER < 0x10100000L | |
3500 | if ( !method ) | |
3501 | method_name = ATOM_sslv23; | |
3502 | else if ( !PL_get_atom(method, &method_name) ) | |
3503 | return PL_domain_error("ssl_method", method); | |
3504 | ||
3505 | if ( method_name == ATOM_sslv23 ) | |
3506 | ssl_method = SSLv23_method(); | |
3507 | #ifndef OPENSSL_NO_SSL2 | |
3508 | else if ( method_name == ATOM_sslv2 ) | |
3509 | ssl_method = SSLv2_method(); | |
3510 | #endif | |
3511 | #ifndef OPENSSL_NO_SSL3_METHOD | |
3512 | else if ( method_name == ATOM_sslv3 ) | |
3513 | ssl_method = SSLv3_method(); | |
3514 | #endif | |
3515 | #ifdef SSL_OP_NO_TLSv1 | |
3516 | else if ( method_name == ATOM_tlsv1 ) | |
3517 | ssl_method = TLSv1_method(); | |
3518 | #endif | |
3519 | #ifdef SSL_OP_NO_TLSv1_1 | |
3520 | else if ( method_name == ATOM_tlsv1_1 ) | |
3521 | ssl_method = TLSv1_1_method(); | |
3522 | #endif | |
3523 | #ifdef SSL_OP_NO_TLSv1_2 | |
3524 | else if ( method_name == ATOM_tlsv1_2 ) | |
3525 | ssl_method = TLSv1_2_method(); | |
3526 | #endif | |
3527 | else | |
3528 | return PL_domain_error("ssl_method", method); | |
3529 | #else | |
3530 | ssl_method = TLS_method(); /* In OpenSSL >= 1.1.0, always use TLS_method() */ | |
3531 | #endif | |
3532 | ||
3533 | return ssl_method; | |
3534 | } | |
3535 | ||
3536 | ||
3537 | static cacert_stack *root_cacert_stack = NULL; | |
3538 | ||
3539 | static int | |
3540 | add_system_root_certificates(cacert_stack *stack) | |
3541 | { STACK_OF(X509) *system_certs = system_root_certificates(); | |
3542 | ||
3543 | if ( system_certs ) | |
3544 | { int index = 0; | |
3545 | ||
3546 | while( index < sk_X509_num(system_certs) ) | |
3547 | { sk_X509_push(stack->cacerts, | |
3548 | X509_dup(sk_X509_value(system_certs, index++))); | |
3549 | } | |
3550 | } | |
3551 | ||
3552 | return TRUE; | |
3553 | } | |
3554 | ||
3555 | ||
3556 | static int | |
3557 | get_cacerts_roots_only(term_t term, cacert_stack **stackp) | |
3558 | { term_t tail = PL_copy_term_ref(term); | |
3559 | term_t head = PL_new_term_ref(); | |
3560 | ||
3561 | if ( PL_get_list(tail, head, tail) && PL_get_nil(tail) && | |
3562 | PL_is_functor(head, FUNCTOR_system1) ) | |
3563 | { atom_t a; | |
3564 | ||
3565 | _PL_get_arg(1, head, head); | |
3566 | if ( PL_get_atom(head, &a) && a == ATOM_root_certificates ) | |
3567 | { if ( root_cacert_stack ) | |
3568 | { *stackp = dup_cacert_stack(root_cacert_stack); | |
3569 | return TRUE; | |
3570 | } else | |
3571 | { cacert_stack *stack; | |
3572 | ||
3573 | if ( !(stack=new_cacert_stack()) || | |
3574 | !add_system_root_certificates(stack) ) | |
3575 | return FALSE; | |
3576 | if ( COMPARE_AND_SWAP_PTR(&root_cacert_stack, NULL, stack) ) | |
3577 | { (void)dup_cacert_stack(root_cacert_stack); | |
3578 | } else | |
3579 | { free_cacert_stack(stack); | |
3580 | } | |
3581 | ||
3582 | *stackp = dup_cacert_stack(root_cacert_stack); | |
3583 | return TRUE; | |
3584 | } | |
3585 | } | |
3586 | } | |
3587 | ||
3588 | return FALSE; | |
3589 | } | |
3590 | ||
3591 | ||
3592 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
3593 | Create a cacert_stack from a Prolog list of certificate sources. The | |
3594 | certificates are all duplicated using X509_dup() such that they can be | |
3595 | freed uniformely when the stack is freed. | |
3596 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
3597 | ||
3598 | static int | |
3599 | get_cacerts(term_t CATail, cacert_stack **stackp) | |
3600 | { term_t CAHead; | |
3601 | cacert_stack *stack; | |
3602 | ||
3603 | if ( get_cacerts_roots_only(CATail, stackp) ) | |
3604 | return TRUE; | |
3605 | ||
3606 | if ( !(CAHead = PL_new_term_ref()) ) | |
3607 | return FALSE; | |
3608 | ||
3609 | if ( !(stack=new_cacert_stack()) ) | |
3610 | { PL_resource_error("memory"); | |
3611 | return FALSE; | |
3612 | } | |
3613 | ||
3614 | while( PL_get_list_ex(CATail, CAHead, CATail) ) | |
3615 | { X509* cert = NULL; | |
3616 | ||
3617 | if ( PL_is_functor(CAHead, FUNCTOR_certificate1) ) | |
3618 | { _PL_get_arg(1, CAHead, CAHead); | |
3619 | ||
3620 | if ( !get_certificate_blob(CAHead, &cert) ) | |
3621 | { error: | |
3622 | free_cacert_stack(stack); | |
3623 | return FALSE; | |
3624 | } | |
3625 | sk_X509_push(stack->cacerts, X509_dup(cert)); | |
3626 | } else if ( PL_is_functor(CAHead, FUNCTOR_file1) ) | |
3627 | { char *file; | |
3628 | ||
3629 | _PL_get_arg(1, CAHead, CAHead); | |
3630 | ||
3631 | if ( !PL_get_file_name(CAHead, &file, PL_FILE_EXIST) || | |
3632 | !load_certificates_from_file(file, stack->cacerts)) | |
3633 | goto error; | |
3634 | } else if ( PL_is_functor(CAHead, FUNCTOR_system1) ) | |
3635 | { atom_t a; | |
3636 | ||
3637 | _PL_get_arg(1, CAHead, CAHead); | |
3638 | ||
3639 | if ( !PL_get_atom_ex(CAHead, &a) ) | |
3640 | goto error; | |
3641 | ||
3642 | if ( a == ATOM_root_certificates ) | |
3643 | { if ( !add_system_root_certificates(stack) ) | |
3644 | goto error; | |
3645 | } | |
3646 | } | |
3647 | } | |
3648 | ||
3649 | if ( !PL_get_nil_ex(CATail) ) | |
3650 | goto error; | |
3651 | ||
3652 | *stackp = stack; | |
3653 | return TRUE; | |
3654 | } | |
3655 | ||
3656 | ||
3657 | ||
3414 | 3658 | static foreign_t |
3415 | 3659 | pl_ssl_context(term_t role, term_t config, term_t options, term_t method) |
3416 | 3660 | { atom_t a; |
3419 | 3663 | term_t tail; |
3420 | 3664 | term_t head = PL_new_term_ref(); |
3421 | 3665 | module_t module = NULL; |
3422 | #if OPENSSL_VERSION_NUMBER < 0x10100000L | |
3423 | atom_t method_name; | |
3424 | #endif | |
3425 | const SSL_METHOD *ssl_method = NULL; | |
3666 | const SSL_METHOD *ssl_method; | |
3426 | 3667 | |
3427 | 3668 | if ( !PL_strip_module(options, &module, options) ) |
3428 | 3669 | return FALSE; |
3437 | 3678 | else |
3438 | 3679 | return PL_domain_error("ssl_role", role); |
3439 | 3680 | |
3440 | #if OPENSSL_VERSION_NUMBER < 0x10100000L | |
3441 | if (!PL_get_atom(method, &method_name)) | |
3442 | return PL_domain_error("ssl_method", method); | |
3443 | if (method_name == ATOM_sslv23) | |
3444 | ssl_method = SSLv23_method(); | |
3445 | #ifndef OPENSSL_NO_SSL2 | |
3446 | else if (method_name == ATOM_sslv2) | |
3447 | ssl_method = SSLv2_method(); | |
3448 | #endif | |
3449 | #ifndef OPENSSL_NO_SSL3_METHOD | |
3450 | else if (method_name == ATOM_sslv3) | |
3451 | ssl_method = SSLv3_method(); | |
3452 | #endif | |
3453 | #ifdef SSL_OP_NO_TLSv1 | |
3454 | else if (method_name == ATOM_tlsv1) | |
3455 | ssl_method = TLSv1_method(); | |
3456 | #endif | |
3457 | #ifdef SSL_OP_NO_TLSv1_1 | |
3458 | else if (method_name == ATOM_tlsv1_1) | |
3459 | ssl_method = TLSv1_1_method(); | |
3460 | #endif | |
3461 | #ifdef SSL_OP_NO_TLSv1_2 | |
3462 | else if (method_name == ATOM_tlsv1_2) | |
3463 | ssl_method = TLSv1_2_method(); | |
3464 | #endif | |
3465 | else | |
3466 | return PL_domain_error("ssl_method", method); | |
3467 | #else | |
3468 | ssl_method = TLS_method(); /* In OpenSSL >= 1.1.0, always use TLS_method() */ | |
3469 | #endif | |
3681 | if ( !(ssl_method = get_ssl_method(method)) ) | |
3682 | return FALSE; | |
3470 | 3683 | |
3471 | 3684 | if ( !(conf = ssl_init(r, ssl_method)) ) |
3472 | 3685 | return PL_resource_error("memory"); |
3686 | ||
3473 | 3687 | while( PL_get_list(tail, head, tail) ) |
3474 | 3688 | { atom_t name; |
3475 | 3689 | size_t arity; |
3476 | 3690 | |
3477 | if ( !PL_get_name_arity(head, &name, &arity) ) | |
3691 | if ( !(PL_get_name_arity(head, &name, &arity) && arity == 1) ) | |
3478 | 3692 | return PL_type_error("ssl_option", head); |
3479 | 3693 | |
3480 | if ( name == ATOM_password && arity == 1 ) | |
3694 | if ( name == ATOM_password ) | |
3481 | 3695 | { char *s; |
3482 | 3696 | |
3483 | 3697 | if ( !get_char_arg(1, head, &s) ) |
3484 | 3698 | return FALSE; |
3485 | 3699 | |
3486 | if (conf->password) free(conf->password); | |
3487 | conf->password = ssl_strdup(s); | |
3488 | } else if ( name == ATOM_require_crl && arity == 1 ) | |
3700 | set_string(conf, password, s); | |
3701 | } else if ( name == ATOM_require_crl ) | |
3489 | 3702 | { int val; |
3490 | 3703 | |
3491 | 3704 | if ( !get_bool_arg(1, head, &val) ) |
3492 | 3705 | return FALSE; |
3493 | 3706 | |
3494 | 3707 | conf->crl_required = val; |
3495 | } else if ( name == ATOM_crl && arity == 1 ) | |
3708 | } else if ( name == ATOM_crl ) | |
3496 | 3709 | { STACK_OF(X509_CRL) *crls = sk_X509_CRL_new_null(); |
3497 | 3710 | term_t list_head = PL_new_term_ref(); |
3498 | 3711 | term_t list_tail = PL_new_term_ref(); |
3712 | ||
3499 | 3713 | _PL_get_arg(1, head, list_tail); |
3500 | 3714 | while( PL_get_list(list_tail, list_head, list_tail) ) |
3501 | 3715 | { atom_t crl_name; |
3512 | 3726 | if (conf->crl_list) |
3513 | 3727 | sk_X509_CRL_pop_free(conf->crl_list, X509_CRL_free); |
3514 | 3728 | conf->crl_list = crls; |
3515 | } else if ( name == ATOM_certificate_file && arity == 1 ) | |
3729 | } else if ( name == ATOM_certificate_file ) | |
3516 | 3730 | { char *file; |
3517 | 3731 | |
3518 | 3732 | if ( !get_file_arg(1, head, &file) ) |
3519 | 3733 | return FALSE; |
3520 | 3734 | |
3521 | if (conf->certificate_file) free(conf->certificate_file); | |
3522 | conf->certificate_file = ssl_strdup(file); | |
3523 | } else if ( name == ATOM_cacerts && arity == 1 ) | |
3524 | { term_t CATail = PL_new_term_ref(); | |
3525 | term_t CAHead = PL_new_term_ref(); | |
3526 | _PL_get_arg(1, head, CATail); | |
3527 | if (conf->cacerts) | |
3528 | sk_X509_pop_free(conf->cacerts, X509_free); | |
3529 | conf->cacerts = sk_X509_new_null(); | |
3530 | while (PL_get_list_ex(CATail, CAHead, CATail)) | |
3531 | { X509* cert = NULL; | |
3532 | if (PL_is_functor(CAHead, FUNCTOR_certificate1)) | |
3533 | { _PL_get_arg(1, CAHead, CAHead); | |
3534 | if (!get_certificate_blob(CAHead, &cert)) | |
3535 | { sk_X509_pop_free(conf->cacerts, X509_free); | |
3536 | conf->cacerts = NULL; | |
3537 | return FALSE; | |
3538 | } | |
3539 | /* Duplicate the certificate here so that if it is freed by AGC the | |
3540 | certificate is still valid in conf->cacerts. | |
3541 | The duplicates will be cleaned up when the conf is freed | |
3542 | */ | |
3543 | sk_X509_push(conf->cacerts, X509_dup(cert)); | |
3544 | } | |
3545 | else if (PL_is_functor(CAHead, FUNCTOR_file1)) | |
3546 | { char *file; | |
3547 | _PL_get_arg(1, CAHead, CAHead); | |
3548 | /* These certificate(s) will be cleaned up when the conf is freed */ | |
3549 | if ( !PL_get_file_name(CAHead, &file, PL_FILE_EXIST) || !load_certificates_from_file(file, conf->cacerts)) | |
3550 | { sk_X509_pop_free(conf->cacerts, X509_free); | |
3551 | conf->cacerts = NULL; | |
3552 | return FALSE; | |
3553 | } | |
3554 | } | |
3555 | else if (PL_is_functor(CAHead, FUNCTOR_system1)) | |
3556 | { _PL_get_arg(1, CAHead, CAHead); | |
3557 | atom_t a; | |
3558 | if ( !PL_get_atom_ex(CAHead, &a) ) | |
3559 | return FALSE; | |
3560 | if ( a == ATOM_root_certificates ) | |
3561 | { STACK_OF(X509) *system_certs = system_root_certificates(); | |
3562 | if ( system_certs ) | |
3563 | { int index = 0; | |
3564 | /* We make a copy of all the system certs here since we later free all the | |
3565 | certificates and do not want to free the ones in the system_root_certificates | |
3566 | stack. The duplicates will be cleaned up when the conf is freed | |
3567 | */ | |
3568 | while (index < sk_X509_num(system_certs)) | |
3569 | { sk_X509_push(conf->cacerts, X509_dup(sk_X509_value(system_certs, index++))); | |
3570 | } | |
3571 | } | |
3572 | } | |
3573 | } | |
3735 | set_string(conf, certificate_file, file); | |
3736 | } else if ( name == ATOM_cacerts ) | |
3737 | { term_t arg = PL_new_term_ref(); | |
3738 | cacert_stack *stack; | |
3739 | ||
3740 | _PL_get_arg(1, head, arg); | |
3741 | if ( get_cacerts(arg, &stack) ) | |
3742 | { free_cacert_stack(conf->cacerts); | |
3743 | conf->cacerts = stack; | |
3574 | 3744 | } |
3575 | if (!PL_get_nil_ex(CATail)) | |
3576 | { sk_X509_pop_free(conf->cacerts, X509_free); | |
3577 | conf->cacerts = NULL; | |
3578 | return FALSE; | |
3579 | } | |
3580 | } else if ( name == ATOM_certificate_file && arity == 1 ) | |
3745 | } else if ( name == ATOM_certificate_file ) | |
3581 | 3746 | { char *file; |
3582 | 3747 | |
3583 | 3748 | if ( !get_file_arg(1, head, &file) ) |
3584 | 3749 | return FALSE; |
3585 | 3750 | |
3586 | if (conf->certificate_file) free(conf->certificate_file); | |
3587 | conf->certificate_file = ssl_strdup(file); | |
3588 | } else if ( name == ATOM_certificate_key_pairs && arity == 1 ) | |
3751 | set_string(conf, certificate_file, file); | |
3752 | } else if ( name == ATOM_certificate_key_pairs ) | |
3589 | 3753 | { term_t cert_head = PL_new_term_ref(); |
3590 | 3754 | term_t cert_tail = PL_new_term_ref(); |
3591 | 3755 | _PL_get_arg(1, head, cert_tail); |
3615 | 3779 | } |
3616 | 3780 | if ( !PL_get_nil_ex(cert_tail) ) |
3617 | 3781 | return FALSE; |
3618 | } else if ( name == ATOM_key_file && arity == 1 ) | |
3782 | } else if ( name == ATOM_key_file ) | |
3619 | 3783 | { char *file; |
3620 | 3784 | |
3621 | 3785 | if ( !get_file_arg(1, head, &file) ) |
3622 | 3786 | return FALSE; |
3623 | 3787 | |
3624 | if (conf->key_file) free(conf->key_file); | |
3625 | conf->key_file = ssl_strdup(file); | |
3626 | } else if ( name == ATOM_pem_password_hook && arity == 1 ) | |
3788 | set_string(conf, key_file, file); | |
3789 | } else if ( name == ATOM_pem_password_hook ) | |
3627 | 3790 | { term_t cb = PL_new_term_ref(); |
3628 | 3791 | _PL_get_arg(1, head, cb); |
3629 | 3792 | conf->cb_pem_passwd.goal = PL_record(cb); |
3788 | 3951 | } |
3789 | 3952 | } |
3790 | 3953 | |
3791 | /* This is used to avoid casting a function pointer. The second argument of sk_X509_deep_copy | |
3792 | expects a function with a const argument | |
3793 | */ | |
3794 | static X509 *x509dup(const X509 *cx) | |
3795 | { X509 *x = (X509 *)cx; | |
3796 | return X509_dup(x); | |
3797 | } | |
3798 | ||
3799 | 3954 | static foreign_t |
3800 | pl_ssl_init_from_context(term_t term_old, term_t term_new) | |
3801 | { | |
3802 | PL_SSL *old, *new; | |
3955 | pl_ssl_copy_context(term_t term_old, term_t term_new) | |
3956 | { PL_SSL *old, *new; | |
3803 | 3957 | int idx; |
3804 | ||
3805 | if ( !get_conf(term_old, &old) || | |
3806 | !get_conf(term_new, &new) ) | |
3958 | const SSL_METHOD *ssl_method; | |
3959 | ||
3960 | if ( !PL_is_variable(term_new) ) | |
3961 | return PL_uninstantiation_error(term_new); | |
3962 | ||
3963 | if ( !get_conf(term_old, &old) ) | |
3807 | 3964 | return FALSE; |
3808 | 3965 | |
3966 | if ( !(ssl_method = get_ssl_method(0)) ) | |
3967 | return FALSE; | |
3968 | if ( !(new = ssl_init(old->role, ssl_method)) ) | |
3969 | return PL_resource_error("memory"); | |
3970 | if ( !unify_conf(term_new, new) ) | |
3971 | return FALSE; /* TBD: cleanup */ | |
3972 | ||
3809 | 3973 | new->role = old->role; |
3810 | ||
3811 | new->password = ssl_strdup(old->password); | |
3812 | ||
3813 | 3974 | new->close_parent = old->close_parent; |
3814 | 3975 | new->close_notify = old->close_notify; |
3815 | new->host = ssl_strdup(old->host); | |
3816 | new->cacerts = old->cacerts?sk_X509_deep_copy(old->cacerts, x509dup, X509_free):NULL; | |
3817 | new->certificate_file = ssl_strdup(old->certificate_file); | |
3818 | new->key_file = ssl_strdup(old->key_file); | |
3819 | 3976 | new->min_protocol = old->min_protocol; |
3820 | 3977 | new->max_protocol = old->max_protocol; |
3821 | 3978 | new->peer_cert_required = old->peer_cert_required; |
3822 | new->cipher_list = ssl_strdup(old->cipher_list); | |
3823 | new->ecdh_curve = ssl_strdup(old->ecdh_curve); | |
3979 | ||
3980 | set_string(new, password, old->password); | |
3981 | set_string(new, host, old->host); | |
3982 | set_string(new, certificate_file, old->certificate_file); | |
3983 | set_string(new, key_file, old->key_file); | |
3984 | set_string(new, cipher_list, old->cipher_list); | |
3985 | set_string(new, ecdh_curve, old->ecdh_curve); | |
3986 | ||
3987 | new->cacerts = dup_cacert_stack(old->cacerts); | |
3824 | 3988 | |
3825 | 3989 | #ifndef HAVE_X509_CHECK_HOST |
3826 | 3990 | new->hostname_check_status = old->hostname_check_status; |
3827 | 3991 | #endif |
3828 | 3992 | |
3829 | if (old->crl_list) | |
3993 | if ( old->crl_list ) | |
3830 | 3994 | new->crl_list = sk_X509_CRL_dup(old->crl_list); |
3831 | 3995 | new->crl_required = old->crl_required; |
3832 | 3996 | |
3833 | 3997 | ssl_copy_callback(old->cb_cert_verify, &new->cb_cert_verify); |
3834 | ssl_copy_callback(old->cb_pem_passwd, &new->cb_pem_passwd); | |
3835 | ssl_copy_callback(old->cb_sni, &new->cb_sni); | |
3836 | ssl_copy_callback(old->cb_alpn_proto, &new->cb_alpn_proto); | |
3837 | ||
3838 | for (idx = 0; idx < old->num_cert_key_pairs; idx++) | |
3998 | ssl_copy_callback(old->cb_pem_passwd, &new->cb_pem_passwd); | |
3999 | ssl_copy_callback(old->cb_sni, &new->cb_sni); | |
4000 | ssl_copy_callback(old->cb_alpn_proto, &new->cb_alpn_proto); | |
4001 | ||
4002 | for(idx = 0; idx < old->num_cert_key_pairs; idx++) | |
3839 | 4003 | { new->cert_key_pairs[idx].certificate = ssl_strdup(old->cert_key_pairs[idx].certificate); |
3840 | 4004 | new->cert_key_pairs[idx].key = ssl_strdup(old->cert_key_pairs[idx].key); |
3841 | 4005 | new->num_cert_key_pairs++; |
3842 | 4006 | } |
3843 | 4007 | |
3844 | if ( old->alpn_protos ) { | |
3845 | unsigned char *protos_copy = malloc(old->alpn_protos_len * sizeof(unsigned char)); | |
4008 | if ( old->alpn_protos ) | |
4009 | { unsigned char *protos_copy = malloc(old->alpn_protos_len * | |
4010 | sizeof(unsigned char)); | |
3846 | 4011 | if ( protos_copy == NULL ) |
3847 | 4012 | return PL_resource_error("memory"); |
3848 | 4013 | memcpy(old->alpn_protos, protos_copy, old->alpn_protos_len); |
4243 | 4408 | FUNCTOR_certificate1 = PL_new_functor(PL_new_atom("certificate"), 1); |
4244 | 4409 | FUNCTOR_file1 = PL_new_functor(PL_new_atom("file"), 1); |
4245 | 4410 | PL_register_foreign("_ssl_context", 4, pl_ssl_context, 0); |
4246 | PL_register_foreign("_ssl_init_from_context", | |
4247 | 2, pl_ssl_init_from_context, 0); | |
4411 | PL_register_foreign("ssl_copy_context", 2, pl_ssl_copy_context, 0); | |
4248 | 4412 | PL_register_foreign("ssl_negotiate", 5, pl_ssl_negotiate, 0); |
4249 | 4413 | PL_register_foreign("_ssl_add_certificate_key", |
4250 | 4414 | 3, pl_ssl_add_certificate_key, 0); |
4251 | 4415 | PL_register_foreign("_ssl_set_options", 2, pl_ssl_set_options, 0); |
4416 | PL_register_foreign("ssl_property", 2, pl_ssl_property, 0); | |
4252 | 4417 | PL_register_foreign("ssl_debug", 1, pl_ssl_debug, 0); |
4253 | 4418 | PL_register_foreign("ssl_session", 2, pl_ssl_session, 0); |
4254 | 4419 | PL_register_foreign("ssl_peer_certificate", |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2013-2018, University of Amsterdam | |
5 | Copyright (c) 2013-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | CWI, Amsterdam |
8 | 8 | All rights reserved. |
37 | 37 | [ test_ssl/0 |
38 | 38 | ]). |
39 | 39 | |
40 | :- asserta(user:file_search_path(library, '.')). | |
41 | :- asserta(user:file_search_path(library, '../clib')). | |
42 | :- asserta(user:file_search_path(library, '..')). | |
43 | :- asserta(user:file_search_path(library, '../plunit')). | |
44 | :- asserta(user:file_search_path(library, '../sgml')). | |
45 | :- asserta(user:file_search_path(foreign, '../clib')). | |
46 | :- asserta(user:file_search_path(foreign, '.')). | |
47 | :- asserta(user:file_search_path(foreign, '../http')). | |
48 | :- asserta(user:file_search_path(foreign, '../sgml')). | |
49 | :- prolog_load_context(directory, D), | |
50 | asserta(user:file_search_path(library, D)). | |
51 | ||
52 | 40 | :- use_module(library(plunit)). |
53 | 41 | :- use_module(library(ssl)). |
54 | 42 | :- use_module(library(crypto)). |
56 | 44 | :- use_module(library(error)). |
57 | 45 | :- use_module(library(readutil)). |
58 | 46 | :- use_module(library(socket)). |
59 | :- use_module(library(https)). | |
47 | :- use_module(https). | |
60 | 48 | |
61 | 49 | %:- debug(connection). |
62 | 50 | %:- debug(certificate). |
237 | 225 | |
238 | 226 | :- begin_tests(ssl_server). |
239 | 227 | |
228 | % This test creates a server and client and tests the following | |
229 | % sequence: | |
230 | % | |
231 | % - Client sends "Hello world" and reads the reply with a 1 sec | |
232 | % timeout. | |
233 | % - Server reads "Hello world", _waits_ 1.5 sec before echoing it. | |
234 | % - Client gets a timeout and retries the read. Second try should | |
235 | % read "Hello world" | |
236 | % - Client sends "bye", going through the same cycle as above. | |
237 | % (JW: Why a second time?) | |
238 | % - Client closes connection. | |
239 | % - Server reads 'end_of_file' and closes the connection. | |
240 | ||
240 | 241 | test(server) :- |
241 | 242 | make_server(SSL, Socket), |
242 | 243 | thread_create(server_loop(SSL, Socket), Id, []), |
246 | 247 | report_join_status(Status) |
247 | 248 | ; format(user_error, 'Client error:~n', []), |
248 | 249 | print_message(error, E), |
250 | thread_signal(Id, abort), | |
249 | 251 | thread_join(Id, Status), |
250 | 252 | report_join_status(Status), |
251 | 253 | fail |
253 | 255 | ). |
254 | 256 | |
255 | 257 | report_join_status(true). |
258 | report_join_status('$aborted'). % we killed the server. | |
256 | 259 | report_join_status(false) :- |
257 | 260 | print_message(error, goal_failed(server_loop(_))). |
258 | 261 | report_join_status(exception(Term)) :- |
285 | 288 | certificate_file('tests/test_certs/server-cert.pem'), |
286 | 289 | key_file('tests/test_certs/server-key.pem'), |
287 | 290 | cert_verify_hook(get_cert_verify), |
288 | % password('apenoot1'), | |
289 | 291 | pem_password_hook(get_server_pwd) |
290 | 292 | ]), |
291 | % Port = 1111, | |
292 | 293 | tcp_socket(Socket), |
293 | 294 | tcp_setopt(Socket, reuseaddr), |
294 | 295 | tcp_bind(Socket, localhost:Port), |
317 | 318 | read_line_to_codes(In, Line), |
318 | 319 | ( Line == end_of_file |
319 | 320 | -> true |
320 | ; debug(data, 'SERVER: Got ~s~n', [Line]), | |
321 | ; debug(data, 'SERVER: Got ~s (sleeping 1.5 sec)', [Line]), | |
321 | 322 | sleep(1.5), |
322 | debug(data, 'SERVER: writing ~s~n', [Line]), | |
323 | debug(data, 'SERVER: writing ~s', [Line]), | |
323 | 324 | format(Out, '~s~n', [Line]), |
324 | 325 | flush_output(Out), |
325 | 326 | ( atom_codes(bye, Line) |
360 | 361 | certificate_file('tests/test_certs/client-cert.pem'), |
361 | 362 | key_file('tests/test_certs/client-key.pem'), |
362 | 363 | close_parent(true), |
363 | % password('apenoot2'), | |
364 | 364 | pem_password_hook(get_client_pwd) |
365 | 365 | ]), |
366 | 366 | client_loop(SSL). |
382 | 382 | call_cleanup(close(In), close(Out)). |
383 | 383 | |
384 | 384 | write_server(Message, In, Out) :- |
385 | debug(data, 'CLIENT: writing: ~q~n', [Message]), | |
385 | debug(data, 'CLIENT: writing: ~q', [Message]), | |
386 | 386 | write(Out, Message), nl(Out), |
387 | 387 | flush_output(Out), |
388 | 388 | sleep(0.1), |
389 | debug(data, 'CLIENT: attempting to read reply (timeout 1 sec)', []), | |
389 | 390 | catch(read_from_server(In, Message), |
390 | 391 | E, |
391 | debug(data, 'CLIENT: exception: ~q~n', [E])), | |
392 | debug(data, 'CLIENT: exception: ~q', [E])), | |
392 | 393 | ( var(E) |
393 | 394 | -> true |
394 | ; read_from_server(In, Message) | |
395 | ; debug(data, 'CLIENT: retrying read reply (timeout 1 sec)', []), | |
396 | read_from_server(In, Message) | |
395 | 397 | ). |
396 | 398 | |
397 | 399 | read_from_server(In, Message) :- |
398 | debug(data, 'CLIENT: attempting to read reply from stream~n', []), | |
399 | 400 | read_line_to_codes(In, Line), |
400 | 401 | ( Line == end_of_file |
401 | 402 | -> true |
402 | 403 | ; atom_codes(Reply, Line), |
403 | debug(data, 'CLIENT: Got ~q~n', [Reply]), | |
404 | debug(data, 'CLIENT: Got ~q', [Reply]), | |
404 | 405 | ( Reply == Message |
405 | 406 | -> true |
406 | 407 | ; format(user_error, 'CLIENT: ERROR: Sent ~q, Got ~q~n', |
305 | 305 | atom_codes(RawSignatureValue, RawSignatureCodes), |
306 | 306 | delete_newlines(RawSignatureCodes, SignatureCodes), |
307 | 307 | string_codes(SignatureValue, SignatureCodes), |
308 | memberchk(element(ns(_, NSRef):'SignedInfo', SignedInfoAttributes, SignedInfo), Signature), | |
309 | SignedData = element(ns(_, NSRef):'SignedInfo', SignedInfoAttributes, SignedInfo), | |
308 | memberchk(element(ns(Prefix, NSRef):'SignedInfo', SignedInfoAttributes, SignedInfo), Signature), | |
309 | SignedData = element(ns(Prefix, NSRef):'SignedInfo', SignedInfoAttributes, SignedInfo), | |
310 | 310 | memberchk(element(ns(_, NSRef):'CanonicalizationMethod', CanonicalizationMethodAttributes, _), SignedInfo), |
311 | 311 | memberchk('Algorithm'=CanonicalizationMethod, CanonicalizationMethodAttributes), |
312 | 312 | forall(memberchk(element(ns(_, NSRef):'Reference', ReferenceAttributes, Reference), SignedInfo), |
0 | # Transparent Inter-Process Communications (TIPC) Sockets. | |
1 | ||
2 | TIPC provides a framework for inter-process communication between | |
3 | federations of trusted peers that are cooperating as a unit. It was | |
4 | developed by Ericsson AB, as a means to provide for communications | |
5 | between Common Control Systems processes and Network Element peers in | |
6 | telephone switching systems, sometimes operating at arm's length on | |
7 | different line cards or mainframes. Delegation of responsibility in this | |
8 | way is one of the fundamental precepts of the Erlang programming system, | |
9 | also developed at Ericsson. TIPC represents a more generalized version | |
10 | of the same behavioral design pattern. | |
11 | ||
12 | This document was produced using PlDoc, with sources found in tipc.pl | |
13 | and tipc_overview.md. | |
14 | ||
15 | @author: Jeffrey Rosenwald (JeffRose@acm.org) | |
16 | @license: BSD-2 | |
17 | @compat: Linux only |
0 | # Transparent Inter-Process Communications (TIPC) Sockets. | |
1 | ||
2 | TIPC provides a framework for inter-process communication between | |
3 | federations of trusted peers that are cooperating as a unit. It was | |
4 | developed by Ericsson AB, as a means to provide for communications | |
5 | between Common Control Systems processes and Network Element peers in | |
6 | telephone switching systems, sometimes operating at arm's length on | |
7 | different line cards or mainframes. Delegation of responsibility in this | |
8 | way is one of the fundamental precepts of the Erlang programming system, | |
9 | also developed at Ericsson. TIPC represents a more generalized version | |
10 | of the same behavioral design pattern. | |
11 | ||
12 | This document was produced using PlDoc, with sources found in tipc.pl | |
13 | and tipc_overview.md. | |
14 | ||
15 | @author: Jeffrey Rosenwald (JeffRose@acm.org) | |
16 | @license: BSD-2 | |
17 | @compat: Linux only |
0 | #!/bin/sh | |
1 | # | |
2 | # install - install a program, script, or datafile | |
3 | # This comes from X11R5. | |
4 | # | |
5 | # Calling this script install-sh is preferred over install.sh, to prevent | |
6 | # `make' implicit rules from creating a file called install from it | |
7 | # when there is no Makefile. | |
8 | # | |
9 | # This script is compatible with the BSD install script, but was written | |
10 | # from scratch. | |
11 | # | |
12 | ||
13 | ||
14 | # set DOITPROG to echo to test this script | |
15 | ||
16 | # Don't use :- since 4.3BSD and earlier shells don't like it. | |
17 | doit="${DOITPROG-}" | |
18 | ||
19 | ||
20 | # put in absolute paths if you don't have them in your path; or use env. vars. | |
21 | ||
22 | mvprog="${MVPROG-mv}" | |
23 | cpprog="${CPPROG-cp}" | |
24 | chmodprog="${CHMODPROG-chmod}" | |
25 | chownprog="${CHOWNPROG-chown}" | |
26 | chgrpprog="${CHGRPPROG-chgrp}" | |
27 | stripprog="${STRIPPROG-strip}" | |
28 | rmprog="${RMPROG-rm}" | |
29 | mkdirprog="${MKDIRPROG-mkdir}" | |
30 | ||
31 | tranformbasename="" | |
32 | transform_arg="" | |
33 | instcmd="$mvprog" | |
34 | chmodcmd="$chmodprog 0755" | |
35 | chowncmd="" | |
36 | chgrpcmd="" | |
37 | stripcmd="" | |
38 | rmcmd="$rmprog -f" | |
39 | mvcmd="$mvprog" | |
40 | src="" | |
41 | dst="" | |
42 | dir_arg="" | |
43 | ||
44 | while [ x"$1" != x ]; do | |
45 | case $1 in | |
46 | -c) instcmd="$cpprog" | |
47 | shift | |
48 | continue;; | |
49 | ||
50 | -d) dir_arg=true | |
51 | shift | |
52 | continue;; | |
53 | ||
54 | -m) chmodcmd="$chmodprog $2" | |
55 | shift | |
56 | shift | |
57 | continue;; | |
58 | ||
59 | -o) chowncmd="$chownprog $2" | |
60 | shift | |
61 | shift | |
62 | continue;; | |
63 | ||
64 | -g) chgrpcmd="$chgrpprog $2" | |
65 | shift | |
66 | shift | |
67 | continue;; | |
68 | ||
69 | -s) stripcmd="$stripprog" | |
70 | shift | |
71 | continue;; | |
72 | ||
73 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` | |
74 | shift | |
75 | continue;; | |
76 | ||
77 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` | |
78 | shift | |
79 | continue;; | |
80 | ||
81 | *) if [ x"$src" = x ] | |
82 | then | |
83 | src=$1 | |
84 | else | |
85 | # this colon is to work around a 386BSD /bin/sh bug | |
86 | : | |
87 | dst=$1 | |
88 | fi | |
89 | shift | |
90 | continue;; | |
91 | esac | |
92 | done | |
93 | ||
94 | if [ x"$src" = x ] | |
95 | then | |
96 | echo "install: no input file specified" | |
97 | exit 1 | |
98 | else | |
99 | true | |
100 | fi | |
101 | ||
102 | if [ x"$dir_arg" != x ]; then | |
103 | dst=$src | |
104 | src="" | |
105 | ||
106 | if [ -d $dst ]; then | |
107 | instcmd=: | |
108 | else | |
109 | instcmd=mkdir | |
110 | fi | |
111 | else | |
112 | ||
113 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command | |
114 | # might cause directories to be created, which would be especially bad | |
115 | # if $src (and thus $dsttmp) contains '*'. | |
116 | ||
117 | if [ -f $src -o -d $src ] | |
118 | then | |
119 | true | |
120 | else | |
121 | echo "install: $src does not exist" | |
122 | exit 1 | |
123 | fi | |
124 | ||
125 | if [ x"$dst" = x ] | |
126 | then | |
127 | echo "install: no destination specified" | |
128 | exit 1 | |
129 | else | |
130 | true | |
131 | fi | |
132 | ||
133 | # If destination is a directory, append the input filename; if your system | |
134 | # does not like double slashes in filenames, you may need to add some logic | |
135 | ||
136 | if [ -d $dst ] | |
137 | then | |
138 | dst="$dst"/`basename $src` | |
139 | else | |
140 | true | |
141 | fi | |
142 | fi | |
143 | ||
144 | ## this sed command emulates the dirname command | |
145 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | |
146 | ||
147 | # Make sure that the destination directory exists. | |
148 | # this part is taken from Noah Friedman's mkinstalldirs script | |
149 | ||
150 | # Skip lots of stat calls in the usual case. | |
151 | if [ ! -d "$dstdir" ]; then | |
152 | defaultIFS=' | |
153 | ' | |
154 | IFS="${IFS-${defaultIFS}}" | |
155 | ||
156 | oIFS="${IFS}" | |
157 | # Some sh's can't handle IFS=/ for some reason. | |
158 | IFS='%' | |
159 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` | |
160 | IFS="${oIFS}" | |
161 | ||
162 | pathcomp='' | |
163 | ||
164 | while [ $# -ne 0 ] ; do | |
165 | pathcomp="${pathcomp}${1}" | |
166 | shift | |
167 | ||
168 | if [ ! -d "${pathcomp}" ] ; | |
169 | then | |
170 | $mkdirprog "${pathcomp}" | |
171 | else | |
172 | true | |
173 | fi | |
174 | ||
175 | pathcomp="${pathcomp}/" | |
176 | done | |
177 | fi | |
178 | ||
179 | if [ x"$dir_arg" != x ] | |
180 | then | |
181 | $doit $instcmd $dst && | |
182 | ||
183 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && | |
184 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && | |
185 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && | |
186 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi | |
187 | else | |
188 | ||
189 | # If we're going to rename the final executable, determine the name now. | |
190 | ||
191 | if [ x"$transformarg" = x ] | |
192 | then | |
193 | dstfile=`basename $dst` | |
194 | else | |
195 | dstfile=`basename $dst $transformbasename | | |
196 | sed $transformarg`$transformbasename | |
197 | fi | |
198 | ||
199 | # don't allow the sed command to completely eliminate the filename | |
200 | ||
201 | if [ x"$dstfile" = x ] | |
202 | then | |
203 | dstfile=`basename $dst` | |
204 | else | |
205 | true | |
206 | fi | |
207 | ||
208 | # Make a temp file name in the proper directory. | |
209 | ||
210 | dsttmp=$dstdir/#inst.$$# | |
211 | ||
212 | # Move or copy the file name to the temp name | |
213 | ||
214 | $doit $instcmd $src $dsttmp && | |
215 | ||
216 | trap "rm -f ${dsttmp}" 0 && | |
217 | ||
218 | # and set any options; do chmod last to preserve setuid bits | |
219 | ||
220 | # If any of these fail, we abort the whole thing. If we want to | |
221 | # ignore errors from any of these, just make sure not to ignore | |
222 | # errors from the above "$doit $instcmd $src $dsttmp" command. | |
223 | ||
224 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && | |
225 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && | |
226 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && | |
227 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && | |
228 | ||
229 | # Now rename the file to the real destination. | |
230 | ||
231 | $doit $rmcmd -f $dstdir/$dstfile && | |
232 | $doit $mvcmd $dsttmp $dstdir/$dstfile | |
233 | ||
234 | fi && | |
235 | ||
236 | ||
237 | exit 0 |
2 | 2 | Author: Jeffrey Rosenwald |
3 | 3 | E-mail: jeffrose@acm.org |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2009-2013, Jeffrey Rosenwald | |
5 | Copyright (c) 2009-2020, Jeffrey Rosenwald | |
6 | 6 | All rights reserved. |
7 | 7 | |
8 | 8 | Redistribution and use in source and binary forms, with or without |
57 | 57 | tipc_service_exists/2, % +Address +Timeout |
58 | 58 | tipc_initialize/0 % |
59 | 59 | ]). |
60 | :- use_module(library(apply)). | |
61 | :- use_module(library(lists)). | |
62 | :- use_module(library(shlib)). | |
60 | :- autoload(library(apply),[maplist/3]). | |
61 | :- autoload(library(lists),[member/2]). | |
62 | ||
63 | 63 | :- use_foreign_library(foreign(tipc)). |
64 | 64 | |
65 | 65 | :- multifile tipc_stack_initialize/0. |
35 | 35 | [ tipc_host_to_address/2, % ?Host, ?Address |
36 | 36 | tipc_initialize/0 |
37 | 37 | ]). |
38 | :- use_module(library(tipc/tipc),[tipc_initialize/0]). | |
38 | 39 | |
39 | 40 | /** <module> A TIPC Broadcast Bridge |
40 | 41 | |
233 | 234 | @compat Linux only |
234 | 235 | */ |
235 | 236 | |
236 | :- use_module(tipc). | |
237 | :- use_module(library(broadcast)). | |
238 | :- use_module(library(time)). | |
239 | :- use_module(library(unix)). | |
237 | :- autoload(tipc, | |
238 | [ tipc_get_name/2, | |
239 | tipc_send/4, | |
240 | tipc_socket/2, | |
241 | tipc_close_socket/1, | |
242 | tipc_setopt/2, | |
243 | tipc_bind/3, | |
244 | tipc_receive/4 | |
245 | ]). | |
246 | :- autoload(library(broadcast), | |
247 | [broadcast_request/1,broadcast/1,listen/3,unlisten/1]). | |
248 | :- autoload(library(debug),[assertion/1]). | |
249 | :- autoload(library(time), | |
250 | [call_with_time_limit/2,alarm/3,remove_alarm/1]). | |
240 | 251 | |
241 | 252 | :- require([ thread_self/1 |
242 | 253 | , forall/2 |
57 | 57 | tipc_linda_server/0, % |
58 | 58 | tipc_initialize/0 |
59 | 59 | ]). |
60 | ||
61 | :- use_module(library(tipc/tipc_broadcast)). | |
62 | :- use_module(library(unix)). | |
63 | ||
64 | :- require([ broadcast/1 | |
65 | , broadcast_request/1 | |
66 | , throw/1 | |
67 | , member/2 | |
68 | , must_be/2 | |
69 | , catch/3 | |
70 | , flag/3 | |
71 | , listen/3 | |
72 | , setup_call_cleanup/3 | |
73 | , strip_module/3 | |
74 | ]). | |
75 | ||
60 | :- use_module(library(tipc/tipc),[tipc_initialize/0]). | |
61 | :- autoload(library(broadcast), | |
62 | [listen/3,broadcast_request/1,broadcast/1,unlisten/3]). | |
63 | :- autoload(library(debug),[assertion/1]). | |
64 | :- autoload(library(error),[must_be/2]). | |
65 | :- autoload(library(lists),[member/2]). | |
76 | 66 | |
77 | 67 | /** <module> A Process Communication Interface |
78 | 68 |
39 | 39 | tipc_paxos_on_change/2, % ?Term, +Goal |
40 | 40 | tipc_initialize/0 |
41 | 41 | ]). |
42 | :- use_module(library(tipc/tipc_broadcast)). | |
43 | :- use_module(library(paxos)). | |
42 | :- use_module(library(tipc/tipc_broadcast), [tipc_initialize/0]). | |
43 | :- autoload(library(paxos),[paxos_set/2,paxos_get/2,paxos_on_change/2]). | |
44 | 44 | |
45 | 45 | /** <module> Paxos on TIPC |
46 | 46 |
0 | This directory contains two examples of foreign-language extensions. | |
1 | ||
2 | # dlltest.dll | |
3 | Simple code illustrating very basic functionality of the | |
4 | interface. Load it using: | |
5 | ||
6 | ?- load_foreign_library(dlltest). | |
7 | ||
8 | It defines the following predicates: | |
9 | ||
10 | say_hello(+Text) | |
11 | Shows a simple Windows message-box containing | |
12 | Text. | |
13 | mclock(-MilliSeconds) | |
14 | Return the number of milli-seconds elapsed since | |
15 | the library was loaded. | |
16 | rlc_color(+Which, +R, +G, +B) | |
17 | Set the color of the plwin window. Which is one | |
18 | of {window, text, highlight, highlighttext}, RGB | |
19 | are integers between 0 and 255 for the color | |
20 | components. | |
21 | ||
22 | In addition, it illustrates how to hook into a Prolog abort. | |
23 | ||
24 | # plregtry.dll | |
25 | Defines predicates to access the Windows registry. It is a much | |
26 | more elaborate example, and also a useful library. Its not | |
27 | documented, but with some knowledge of the Windows API it should | |
28 | be fairly easy to figure out how it works. | |
29 | ||
30 | The .dsp files are Microsoft Visual C++ 5.0 project files. Basically, to | |
31 | compile them: | |
32 | ||
33 | * Ensure the compile has the SWI-Prolog include directory | |
34 | in the search-path for header-files. | |
35 | ||
36 | * Ensure the compiler has the SWI-Prolog lib directory in | |
37 | the search-path for libraries. | |
38 | ||
39 | * Ensure WIN32 is a defined symbol (-DWIN32). MSVC normally | |
40 | defines this for you. |
0 | # Foreign language demo for Windows | |
1 | ||
2 | This directory contains two examples of foreign-language extensions. | |
3 | ||
4 | - dlltest.dll | |
5 | Simple code illustrating very basic functionality of the | |
6 | interface. Load it using: | |
7 | ||
8 | ?- load_foreign_library(dlltest). | |
9 | ||
10 | It defines the following predicates: | |
11 | ||
12 | - say_hello(+Text) | |
13 | Shows a simple Windows message-box containing Text. | |
14 | - mclock(-MilliSeconds) | |
15 | Return the number of milli-seconds elapsed since the library was loaded. | |
16 | - rlc_color(+Which, +R, +G, +B) | |
17 | Set the color of the plwin window. Which is one of {window, text, | |
18 | highlight, highlighttext}, RGB are integers between 0 and 255 for | |
19 | the color components. | |
20 | ||
21 | In addition, it illustrates how to hook into a Prolog abort. | |
22 | ||
23 | - plregtry.dll | |
24 | Defines predicates to access the Windows registry. It is a much | |
25 | more elaborate example, and also a useful library. Its not | |
26 | documented, but with some knowledge of the Windows API it should | |
27 | be fairly easy to figure out how it works. |
0 | #!/bin/sh | |
1 | # | |
2 | # install - install a program, script, or datafile | |
3 | # This comes from X11R5. | |
4 | # | |
5 | # Calling this script install-sh is preferred over install.sh, to prevent | |
6 | # `make' implicit rules from creating a file called install from it | |
7 | # when there is no Makefile. | |
8 | # | |
9 | # This script is compatible with the BSD install script, but was written | |
10 | # from scratch. | |
11 | # | |
12 | ||
13 | ||
14 | # set DOITPROG to echo to test this script | |
15 | ||
16 | # Don't use :- since 4.3BSD and earlier shells don't like it. | |
17 | doit="${DOITPROG-}" | |
18 | ||
19 | ||
20 | # put in absolute paths if you don't have them in your path; or use env. vars. | |
21 | ||
22 | mvprog="${MVPROG-mv}" | |
23 | cpprog="${CPPROG-cp}" | |
24 | chmodprog="${CHMODPROG-chmod}" | |
25 | chownprog="${CHOWNPROG-chown}" | |
26 | chgrpprog="${CHGRPPROG-chgrp}" | |
27 | stripprog="${STRIPPROG-strip}" | |
28 | rmprog="${RMPROG-rm}" | |
29 | mkdirprog="${MKDIRPROG-mkdir}" | |
30 | ||
31 | tranformbasename="" | |
32 | transform_arg="" | |
33 | instcmd="$mvprog" | |
34 | chmodcmd="$chmodprog 0755" | |
35 | chowncmd="" | |
36 | chgrpcmd="" | |
37 | stripcmd="" | |
38 | rmcmd="$rmprog -f" | |
39 | mvcmd="$mvprog" | |
40 | src="" | |
41 | dst="" | |
42 | dir_arg="" | |
43 | ||
44 | while [ x"$1" != x ]; do | |
45 | case $1 in | |
46 | -c) instcmd="$cpprog" | |
47 | shift | |
48 | continue;; | |
49 | ||
50 | -d) dir_arg=true | |
51 | shift | |
52 | continue;; | |
53 | ||
54 | -m) chmodcmd="$chmodprog $2" | |
55 | shift | |
56 | shift | |
57 | continue;; | |
58 | ||
59 | -o) chowncmd="$chownprog $2" | |
60 | shift | |
61 | shift | |
62 | continue;; | |
63 | ||
64 | -g) chgrpcmd="$chgrpprog $2" | |
65 | shift | |
66 | shift | |
67 | continue;; | |
68 | ||
69 | -s) stripcmd="$stripprog" | |
70 | shift | |
71 | continue;; | |
72 | ||
73 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` | |
74 | shift | |
75 | continue;; | |
76 | ||
77 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` | |
78 | shift | |
79 | continue;; | |
80 | ||
81 | *) if [ x"$src" = x ] | |
82 | then | |
83 | src=$1 | |
84 | else | |
85 | # this colon is to work around a 386BSD /bin/sh bug | |
86 | : | |
87 | dst=$1 | |
88 | fi | |
89 | shift | |
90 | continue;; | |
91 | esac | |
92 | done | |
93 | ||
94 | if [ x"$src" = x ] | |
95 | then | |
96 | echo "install: no input file specified" | |
97 | exit 1 | |
98 | else | |
99 | true | |
100 | fi | |
101 | ||
102 | if [ x"$dir_arg" != x ]; then | |
103 | dst=$src | |
104 | src="" | |
105 | ||
106 | if [ -d $dst ]; then | |
107 | instcmd=: | |
108 | else | |
109 | instcmd=mkdir | |
110 | fi | |
111 | else | |
112 | ||
113 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command | |
114 | # might cause directories to be created, which would be especially bad | |
115 | # if $src (and thus $dsttmp) contains '*'. | |
116 | ||
117 | if [ -f $src -o -d $src ] | |
118 | then | |
119 | true | |
120 | else | |
121 | echo "install: $src does not exist" | |
122 | exit 1 | |
123 | fi | |
124 | ||
125 | if [ x"$dst" = x ] | |
126 | then | |
127 | echo "install: no destination specified" | |
128 | exit 1 | |
129 | else | |
130 | true | |
131 | fi | |
132 | ||
133 | # If destination is a directory, append the input filename; if your system | |
134 | # does not like double slashes in filenames, you may need to add some logic | |
135 | ||
136 | if [ -d $dst ] | |
137 | then | |
138 | dst="$dst"/`basename $src` | |
139 | else | |
140 | true | |
141 | fi | |
142 | fi | |
143 | ||
144 | ## this sed command emulates the dirname command | |
145 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | |
146 | ||
147 | # Make sure that the destination directory exists. | |
148 | # this part is taken from Noah Friedman's mkinstalldirs script | |
149 | ||
150 | # Skip lots of stat calls in the usual case. | |
151 | if [ ! -d "$dstdir" ]; then | |
152 | defaultIFS=' | |
153 | ' | |
154 | IFS="${IFS-${defaultIFS}}" | |
155 | ||
156 | oIFS="${IFS}" | |
157 | # Some sh's can't handle IFS=/ for some reason. | |
158 | IFS='%' | |
159 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` | |
160 | IFS="${oIFS}" | |
161 | ||
162 | pathcomp='' | |
163 | ||
164 | while [ $# -ne 0 ] ; do | |
165 | pathcomp="${pathcomp}${1}" | |
166 | shift | |
167 | ||
168 | if [ ! -d "${pathcomp}" ] ; | |
169 | then | |
170 | $mkdirprog "${pathcomp}" | |
171 | else | |
172 | true | |
173 | fi | |
174 | ||
175 | pathcomp="${pathcomp}/" | |
176 | done | |
177 | fi | |
178 | ||
179 | if [ x"$dir_arg" != x ] | |
180 | then | |
181 | $doit $instcmd $dst && | |
182 | ||
183 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && | |
184 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && | |
185 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && | |
186 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi | |
187 | else | |
188 | ||
189 | # If we're going to rename the final executable, determine the name now. | |
190 | ||
191 | if [ x"$transformarg" = x ] | |
192 | then | |
193 | dstfile=`basename $dst` | |
194 | else | |
195 | dstfile=`basename $dst $transformbasename | | |
196 | sed $transformarg`$transformbasename | |
197 | fi | |
198 | ||
199 | # don't allow the sed command to completely eliminate the filename | |
200 | ||
201 | if [ x"$dstfile" = x ] | |
202 | then | |
203 | dstfile=`basename $dst` | |
204 | else | |
205 | true | |
206 | fi | |
207 | ||
208 | # Make a temp file name in the proper directory. | |
209 | ||
210 | dsttmp=$dstdir/#inst.$$# | |
211 | ||
212 | # Move or copy the file name to the temp name | |
213 | ||
214 | $doit $instcmd $src $dsttmp && | |
215 | ||
216 | trap "rm -f ${dsttmp}" 0 && | |
217 | ||
218 | # and set any options; do chmod last to preserve setuid bits | |
219 | ||
220 | # If any of these fail, we abort the whole thing. If we want to | |
221 | # ignore errors from any of these, just make sure not to ignore | |
222 | # errors from the above "$doit $instcmd $src $dsttmp" command. | |
223 | ||
224 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && | |
225 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && | |
226 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && | |
227 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && | |
228 | ||
229 | # Now rename the file to the real destination. | |
230 | ||
231 | $doit $rmcmd -f $dstdir/$dstfile && | |
232 | $doit $mvcmd $dsttmp $dstdir/$dstfile | |
233 | ||
234 | fi && | |
235 | ||
236 | ||
237 | exit 0 |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2011-2013, University of Amsterdam | |
5 | Copyright (c) 2011-2020, University of Amsterdam | |
6 | CWI, Amsterdam | |
6 | 7 | All rights reserved. |
7 | 8 | |
8 | 9 | Redistribution and use in source and binary forms, with or without |
52 | 53 | % +IfNotRunning |
53 | 54 | shell_register_prolog/1 % +Extension |
54 | 55 | ]). |
56 | :- autoload(library(lists),[member/2]). | |
55 | 57 | |
56 | 58 | :- use_foreign_library(foreign(plregtry)). % load plregtry.ddl |
57 | 59 |
0 | #!/bin/sh | |
1 | ||
2 | # PLARCH is passed from packages/configure | |
3 | ||
4 | case $PLARCH in | |
5 | *-win32|*-win64) | |
6 | exit 0 | |
7 | ;; | |
8 | *) | |
9 | exit 1 | |
10 | esac |
49 | 49 | ]). |
50 | 50 | |
51 | 51 | :- dynamic |
52 | autoload/2. | |
53 | :- public | |
52 | 54 | autoload/2. |
53 | 55 | |
54 | 56 | %! pce_autoload(+ClassName, +FileSpec) |
64 | 64 | attribute/3, % ClassName, Attribute, Value |
65 | 65 | verbose/0, |
66 | 66 | recording/2. % items recorded |
67 | :- public | |
68 | attribute/3, | |
69 | compiling/2. | |
67 | 70 | |
68 | 71 | :- if(exists_source(library(quintus))). |
69 | 72 | :- use_module(library(quintus), [genarg/3]). |
2 | 2 | Author: Jan Wielemaker and Anjo Anjewierden |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org/projects/xpce/ |
5 | Copyright (c) 1985-2011, University of Amsterdam | |
5 | Copyright (c) 1985-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
36 | 36 | :- require([ send/2, |
37 | 37 | get/3 |
38 | 38 | ]). |
39 | :- public | |
40 | property/1. | |
39 | 41 | |
40 | 42 | /******************************* |
41 | 43 | * PROPERTIES * |
69 | 69 | :- autoload(library(shlib),[load_foreign_library/1]). |
70 | 70 | :- autoload(library(swi_compatibility),[pce_info/1]). |
71 | 71 | :- autoload(library(system),[unlock_predicate/1]). |
72 | ||
73 | :- public | |
74 | in_pce_thread_sync2/2. | |
72 | 75 | |
73 | 76 | :- meta_predicate |
74 | 77 | send_class(+, +, :), |
2 | 2 | Author: Jan Wielemaker and Anjo Anjewierden |
3 | 3 | E-mail: J.Wielemaker@cs.vu.nl |
4 | 4 | WWW: http://www.swi.psy.uva.nl/projects/xpce/ |
5 | Copyright (c) 1985-2013, University of Amsterdam | |
5 | Copyright (c) 1985-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | CWI, Amsterdam | |
7 | 8 | All rights reserved. |
8 | 9 | |
9 | 10 | Redistribution and use in source and binary forms, with or without |
52 | 53 | manpce/1, |
53 | 54 | prolog_ide/1, |
54 | 55 | spypce/1, |
56 | trace/1, | |
55 | 57 | tracepce/1, |
56 | 58 | atomic_list_concat/2, |
57 | 59 | breakpoint_property/2, |
1015 | 1017 | tracepce((Class-Name)). |
1016 | 1018 | do_trace((Head :- _Body), M, Spec) :- |
1017 | 1019 | prolog_debug_spec(M, Head, Spec), |
1018 | user:trace(Spec). | |
1020 | @(trace(Spec), user). | |
1019 | 1021 | do_trace(Head, M, Spec) :- |
1020 | 1022 | prolog_debug_spec(M, Head, Spec), |
1021 | user:trace(Spec). | |
1023 | @(trace(Spec), user). | |
1022 | 1024 | |
1023 | 1025 | prolog_debug_spec(M, Head, Spec) :- |
1024 | 1026 | catch(functor(Head, Name, Arity), _, fail), |
127 | 127 | }, |
128 | 128 | dlist(Codes, Tail), |
129 | 129 | make_message(T). |
130 | make_message([ansi(_Attrs, Fmt, Args)|T]) --> | |
131 | !, | |
132 | { format(codes(Codes, Tail), Fmt, Args) | |
133 | }, | |
134 | dlist(Codes, Tail), | |
135 | make_message(T). | |
136 | make_message([Skip|T]) --> | |
137 | { action_skip(Skip) }, | |
138 | !, | |
139 | make_message(T). | |
130 | 140 | make_message([Fmt|T]) --> |
131 | 141 | make_message([Fmt-[]|T]). |
142 | ||
143 | action_skip(at_same_line). | |
144 | action_skip(flush). | |
145 | action_skip(begin(_Level, _Ctx)). | |
146 | action_skip(end(_Ctx)). | |
132 | 147 | |
133 | 148 | dlist(Codes, Tail, Codes, Tail). |
134 | 149 |
93 | 93 | ). |
94 | 94 | |
95 | 95 | |
96 | ||
97 | 96 | % gzip: can we write (and read back) a compressed file |
98 | 97 | |
98 | :- multifile user:file_search_path/1. | |
99 | user:file_search_path(test_tmp_dir, '.'). | |
100 | ||
101 | tmp_output(Base, File) :- | |
102 | absolute_file_name(test_tmp_dir(Base), | |
103 | File, | |
104 | [ access(write) | |
105 | ]). | |
106 | ||
99 | 107 | test(gzip_ascii, |
100 | [ cleanup(delete_file('plunit-tmp.gz')) | |
101 | ]) :- | |
102 | numlist(0, 127, ReferenceCodes), | |
103 | gzopen('plunit-tmp.gz', write, ZOut, [type(text), encoding(ascii)]), | |
104 | set_stream(ZOut, newline(posix)), | |
105 | format(ZOut, '~s', [ReferenceCodes]), | |
106 | close(ZOut), | |
107 | gzopen('plunit-tmp.gz', read, ZIn, [type(text)]), | |
108 | [ setup(tmp_output('plunit-tmp.gz', Tmp)), | |
109 | cleanup(delete_file(Tmp)) | |
110 | ]) :- | |
111 | numlist(0, 127, ReferenceCodes), | |
112 | gzopen(Tmp, write, ZOut, [type(text), encoding(ascii)]), | |
113 | set_stream(ZOut, newline(posix)), | |
114 | format(ZOut, '~s', [ReferenceCodes]), | |
115 | close(ZOut), | |
116 | gzopen(Tmp, read, ZIn, [type(text)]), | |
108 | 117 | set_stream(ZIn, newline(posix)), |
109 | 118 | call_cleanup(read_stream_to_codes(ZIn, Codes), close(ZIn)), |
110 | 119 | Codes = ReferenceCodes. |
111 | 120 | |
112 | 121 | test(gzip_utf8, |
113 | [ cleanup(delete_file('plunit-tmp.gz')) | |
122 | [ setup(tmp_output('plunit-tmp.gz', Tmp)), | |
123 | cleanup(delete_file(Tmp)) | |
114 | 124 | ]) :- |
115 | 125 | numlist(0, 2047, ReferenceCodes), |
116 | gzopen('plunit-tmp.gz', write, ZOut, [type(text), encoding(utf8)]), | |
117 | set_stream(ZOut, newline(posix)), | |
118 | format(ZOut, '~s', [ReferenceCodes]), | |
119 | close(ZOut), | |
120 | gzopen('plunit-tmp.gz', read, ZIn, [type(text), encoding(utf8)]), | |
126 | gzopen(Tmp, write, ZOut, [type(text), encoding(utf8)]), | |
127 | set_stream(ZOut, newline(posix)), | |
128 | format(ZOut, '~s', [ReferenceCodes]), | |
129 | close(ZOut), | |
130 | gzopen(Tmp, read, ZIn, [type(text), encoding(utf8)]), | |
121 | 131 | set_stream(ZIn, newline(posix)), |
122 | 132 | call_cleanup(read_stream_to_codes(ZIn, Codes), close(ZIn)), |
123 | 133 | Codes = ReferenceCodes. |
124 | 134 | |
125 | 135 | test(gzip_binary, |
126 | [ cleanup(delete_file('plunit-tmp.gz')) | |
136 | [ setup(tmp_output('plunit-tmp.gz', Tmp)), | |
137 | cleanup(delete_file(Tmp)) | |
127 | 138 | ]) :- |
128 | 139 | numlist(0, 255, ReferenceCodes), |
129 | gzopen('plunit-tmp.gz', write, ZOut, [type(binary)]), | |
130 | set_stream(ZOut, newline(posix)), | |
131 | format(ZOut, '~s', [ReferenceCodes]), | |
132 | close(ZOut), | |
133 | gzopen('plunit-tmp.gz', read, ZIn, [type(binary)]), | |
140 | gzopen(Tmp, write, ZOut, [type(binary)]), | |
141 | set_stream(ZOut, newline(posix)), | |
142 | format(ZOut, '~s', [ReferenceCodes]), | |
143 | close(ZOut), | |
144 | gzopen(Tmp, read, ZIn, [type(binary)]), | |
134 | 145 | set_stream(ZIn, newline(posix)), |
135 | 146 | call_cleanup(read_stream_to_codes(ZIn, Codes), close(ZIn)), |
136 | 147 | Codes = ReferenceCodes. |
137 | 148 | |
138 | 149 | test(gzip_empty, |
139 | [ cleanup(delete_file('plunit-tmp.gz')) | |
140 | ]) :- | |
141 | gzopen('plunit-tmp.gz', write, ZOut), | |
142 | close(ZOut), | |
143 | gzopen('plunit-tmp.gz', read, ZIn, [type(text)]), | |
150 | [ setup(tmp_output('plunit-tmp.gz', Tmp)), | |
151 | cleanup(delete_file(Tmp)) | |
152 | ]) :- | |
153 | gzopen(Tmp, write, ZOut), | |
154 | close(ZOut), | |
155 | gzopen(Tmp, read, ZIn, [type(text)]), | |
144 | 156 | call_cleanup(read_stream_to_codes(ZIn, Codes1), close(ZIn)), |
145 | 157 | Codes1 = []. |
146 | 158 | |
147 | 159 | test(gzip_multipart, |
148 | [ cleanup(delete_file('plunit-tmp.gz')) | |
149 | ]) :- | |
150 | gzopen('plunit-tmp.gz', write, ZOut1), | |
160 | [ setup(tmp_output('plunit-tmp.gz', Tmp)), | |
161 | cleanup(delete_file(Tmp)) | |
162 | ]) :- | |
163 | gzopen(Tmp, write, ZOut1), | |
151 | 164 | format(ZOut1, 'Part1\n', []), |
152 | 165 | close(ZOut1), |
153 | gzopen('plunit-tmp.gz', append, ZOut2), | |
166 | gzopen(Tmp, append, ZOut2), | |
154 | 167 | format(ZOut2, 'Part2\n', []), |
155 | 168 | close(ZOut2), |
156 | gzopen('plunit-tmp.gz', read, ZIn), | |
169 | gzopen(Tmp, read, ZIn), | |
157 | 170 | call_cleanup(read_stream_to_codes(ZIn, Codes), close(ZIn)), |
158 | 171 | atom_codes('Part1\nPart2\n', Codes). |
159 | 172 | |
162 | 175 | % deflate: test read/write of deflate format |
163 | 176 | |
164 | 177 | test(deflate_ascii, |
165 | [ cleanup(delete_file('plunit-tmp.z')) | |
166 | ]) :- | |
167 | numlist(0, 127, ReferenceCodes), | |
168 | open('plunit-tmp.z', write, Out, [type(text), encoding(ascii)]), | |
178 | [ setup(tmp_output('plunit-tmp.z', Tmp)), | |
179 | cleanup(delete_file(Tmp)) | |
180 | ]) :- | |
181 | numlist(0, 127, ReferenceCodes), | |
182 | open(Tmp, write, Out, [type(text), encoding(ascii)]), | |
169 | 183 | zopen(Out, ZOut, []), |
170 | 184 | set_stream(ZOut, newline(posix)), |
171 | 185 | format(ZOut, '~s', [ReferenceCodes]), |
172 | 186 | close(ZOut), |
173 | open('plunit-tmp.z', read, In, [type(text), encoding(ascii)]), | |
187 | open(Tmp, read, In, [type(text), encoding(ascii)]), | |
174 | 188 | zopen(In, ZIn, []), |
175 | 189 | set_stream(ZIn, newline(posix)), |
176 | 190 | read_stream_to_codes(ZIn, Codes), |
178 | 192 | Codes == ReferenceCodes. |
179 | 193 | |
180 | 194 | test(deflate_utf8, |
181 | [ cleanup(delete_file('plunit-tmp.z')) | |
195 | [ setup(tmp_output('plunit-tmp.z', Tmp)), | |
196 | cleanup(delete_file(Tmp)) | |
182 | 197 | ]) :- |
183 | 198 | numlist(0, 2047, ReferenceCodes), |
184 | open('plunit-tmp.z', write, Out, [type(text), encoding(utf8)]), | |
199 | open(Tmp, write, Out, [type(text), encoding(utf8)]), | |
185 | 200 | zopen(Out, ZOut, []), |
186 | 201 | set_stream(ZOut, newline(posix)), |
187 | 202 | format(ZOut, '~s', [ReferenceCodes]), |
188 | 203 | close(ZOut), |
189 | open('plunit-tmp.z', read, In, [type(text), encoding(utf8)]), | |
204 | open(Tmp, read, In, [type(text), encoding(utf8)]), | |
190 | 205 | zopen(In, ZIn, []), |
191 | 206 | set_stream(ZIn, newline(posix)), |
192 | 207 | read_stream_to_codes(ZIn, Codes), |
194 | 209 | Codes == ReferenceCodes. |
195 | 210 | |
196 | 211 | test(deflate_binary, |
197 | [ cleanup(delete_file('plunit-tmp.z')) | |
212 | [ setup(tmp_output('plunit-tmp.z', Tmp)), | |
213 | cleanup(delete_file(Tmp)) | |
198 | 214 | ]) :- |
199 | 215 | numlist(0, 255, ReferenceCodes), |
200 | open('plunit-tmp.z', write, Out, [type(binary)]), | |
216 | open(Tmp, write, Out, [type(binary)]), | |
201 | 217 | zopen(Out, ZOut, []), |
202 | 218 | format(ZOut, '~s', [ReferenceCodes]), |
203 | 219 | close(ZOut), |
204 | open('plunit-tmp.z', read, In, [type(binary)]), | |
220 | open(Tmp, read, In, [type(binary)]), | |
205 | 221 | zopen(In, ZIn, []), |
206 | 222 | read_stream_to_codes(ZIn, Codes), |
207 | 223 | close(ZIn), |
208 | 224 | Codes == ReferenceCodes. |
209 | 225 | |
210 | 226 | test(deflate_empty, |
211 | [ cleanup(delete_file('plunit-tmp.z')) | |
212 | ]) :- | |
213 | open('plunit-tmp.z', write, Out), | |
227 | [ setup(tmp_output('plunit-tmp.z', Tmp)), | |
228 | cleanup(delete_file(Tmp)) | |
229 | ]) :- | |
230 | open(Tmp, write, Out), | |
214 | 231 | zopen(Out, ZOut, []), |
215 | 232 | close(ZOut), |
216 | open('plunit-tmp.z', read, In), | |
233 | open(Tmp, read, In), | |
217 | 234 | zopen(In, ZIn, []), |
218 | 235 | read_stream_to_codes(ZIn, Codes), |
219 | 236 | close(ZIn), |
220 | 237 | Codes == []. |
221 | 238 | |
222 | test(deflate_low_compression) :- | |
223 | numlist(0, 127, ReferenceCodes), | |
224 | open('plunit-tmp.z', write, Out), | |
239 | test(deflate_low_compression, | |
240 | [ setup(tmp_output('plunit-tmp.z', Tmp)), | |
241 | cleanup(delete_file(Tmp)) | |
242 | ]) :- | |
243 | numlist(0, 127, ReferenceCodes), | |
244 | open(Tmp, write, Out), | |
225 | 245 | zopen(Out, ZOut, [level(0)]), |
226 | 246 | set_stream(ZOut, newline(posix)), |
227 | 247 | format(ZOut, '~s', [ReferenceCodes]), |
228 | 248 | close(ZOut), |
229 | open('plunit-tmp.z', read, In), | |
230 | zopen(In, ZIn, []), | |
231 | set_stream(ZIn, newline(posix)), | |
232 | read_stream_to_codes(ZIn, Codes), | |
233 | close(ZIn), | |
234 | Codes == ReferenceCodes. | |
235 | ||
236 | test(deflate_high_compression) :- | |
237 | numlist(0, 127, ReferenceCodes), | |
238 | open('plunit-tmp.z', write, Out), | |
249 | open(Tmp, read, In), | |
250 | zopen(In, ZIn, []), | |
251 | set_stream(ZIn, newline(posix)), | |
252 | read_stream_to_codes(ZIn, Codes), | |
253 | close(ZIn), | |
254 | Codes == ReferenceCodes. | |
255 | ||
256 | test(deflate_high_compression, | |
257 | [ setup(tmp_output('plunit-tmp.z', Tmp)), | |
258 | cleanup(delete_file(Tmp)) | |
259 | ]) :- | |
260 | numlist(0, 127, ReferenceCodes), | |
261 | open(Tmp, write, Out), | |
239 | 262 | zopen(Out, ZOut, [level(9)]), |
240 | 263 | set_stream(ZOut, newline(posix)), |
241 | 264 | format(ZOut, '~s', [ReferenceCodes]), |
242 | 265 | close(ZOut), |
243 | open('plunit-tmp.z', read, In), | |
266 | open(Tmp, read, In), | |
244 | 267 | zopen(In, ZIn, []), |
245 | 268 | set_stream(ZIn, newline(posix)), |
246 | 269 | read_stream_to_codes(ZIn, Codes), |
248 | 271 | Codes == ReferenceCodes. |
249 | 272 | |
250 | 273 | test(deflate_multipart, |
251 | [ cleanup(delete_file('plunit-tmp.z')) | |
252 | ]) :- | |
253 | open('plunit-tmp.z', write, Out), | |
274 | [ setup(tmp_output('plunit-tmp.z', Tmp)), | |
275 | cleanup(delete_file(Tmp)) | |
276 | ]) :- | |
277 | open(Tmp, write, Out), | |
254 | 278 | zopen(Out, ZOut1, [close_parent(false)]), |
255 | 279 | format(ZOut1, 'Part1\n', []), |
256 | 280 | close(ZOut1), |
257 | 281 | zopen(Out, ZOut2, []), |
258 | 282 | format(ZOut2, 'Part2\n', []), |
259 | 283 | close(ZOut2), |
260 | open('plunit-tmp.z', read, In), | |
284 | open(Tmp, read, In), | |
261 | 285 | zopen(In, ZIn, [multi_part(true)]), |
262 | 286 | read_stream_to_codes(ZIn, Codes), |
263 | 287 | close(ZIn), |
17 | 17 | |
18 | 18 | printf "Adding Macport dylibs to modules in $moduledir\n" |
19 | 19 | |
20 | changeset="$(echo $moduledir/*)" | |
20 | changeset="$(echo $moduledir/*) $app/Contents/MacOS/swipl" | |
21 | 21 | while [ ! -z "$changeset" ]; do |
22 | 22 | newchanges= |
23 | 23 | for f in $changeset; do |
61 | 61 | A atanh "atanh" |
62 | 62 | A atom "atom" |
63 | 63 | A atom_garbage_collection "atom_garbage_collection" |
64 | A atom_space "atom_space" | |
64 | 65 | A atomic "atomic" |
65 | 66 | A atoms "atoms" |
66 | 67 | A att "att" |
335 | 336 | A full "full" |
336 | 337 | A fullstop "fullstop" |
337 | 338 | A functor_name "functor_name" |
339 | A functor_space "functor_space" | |
338 | 340 | A functors "functors" |
339 | 341 | A fx "fx" |
340 | 342 | A fy "fy" |
372 | 374 | A hide_childs "hide_childs" |
373 | 375 | A history_depth "history_depth" |
374 | 376 | A id "id" |
377 | A idg_affected_count "idg_affected_count" | |
378 | A idg_dependent_count "idg_dependent_count" | |
379 | A idg_size "idg_size" | |
375 | 380 | A ifthen "->" |
376 | 381 | A ignore "ignore" |
377 | 382 | A ignore_ops "ignore_ops" |
689 | 694 | A shared_table_space "shared_table_space" |
690 | 695 | A shell "shell" |
691 | 696 | A shift_time "shift_time" |
697 | A short "short" | |
692 | 698 | A sign "sign" |
693 | 699 | A signal "signal" |
694 | 700 | A signal_handler "signal_handler" |
787 | 793 | A thread_property "thread_property" |
788 | 794 | A threads "threads" |
789 | 795 | A threads_created "threads_created" |
796 | A threads_peak "threads_peak" | |
790 | 797 | A trienode "trienode" |
791 | 798 | A tripwire "tripwire" |
792 | 799 | A throw "throw" |
322 | 322 | if(HAVE_LIBRT) |
323 | 323 | set(LIBSWIPL_LIBRARIES ${LIBSWIPL_LIBRARIES} rt) |
324 | 324 | endif() |
325 | if(HAVE_LIBATOMIC) | |
326 | set(LIBSWIPL_LIBRARIES ${LIBSWIPL_LIBRARIES} atomic) | |
327 | endif() | |
328 | if(LIBTCMALLOC_LIBRARIES) | |
329 | set(SWIPL_LIBRARIES ${LIBTCMALLOC_LIBRARIES} ${SWIPL_LIBRARIES}) | |
330 | endif() | |
325 | 331 | |
326 | 332 | # build swipl |
327 | 333 | add_executable(swipl ${SWIPL_SRC}) |
328 | target_link_libraries(swipl libswipl) | |
334 | target_link_libraries(swipl ${SWIPL_LIBRARIES} libswipl) | |
329 | 335 | target_c_stack(swipl 4000000) |
330 | 336 | |
331 | 337 | # build the library |
472 | 478 | COMMAND ${PROG_SWIPL} -f none --no-packs -q ${CMAKE_CURRENT_SOURCE_DIR}/test.pl --no-core ${test}) |
473 | 479 | endforeach() |
474 | 480 | |
475 | if(INSTALL_TESTS) | |
476 | #Copy core tests to the installation | |
481 | # Use a function to scope CMAKE_INSTALL_DEFAULT_COMPONENT_NAME | |
482 | function(install_tests) | |
483 | set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Tests) | |
477 | 484 | install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Tests |
478 | 485 | DESTINATION ${INSTALL_TESTS_DIR}) |
479 | 486 | install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/test.pl |
480 | 487 | DESTINATION ${INSTALL_TESTS_DIR}/) |
488 | endfunction() | |
489 | ||
490 | if(INSTALL_TESTS) | |
491 | install_tests() | |
481 | 492 | endif() |
482 | 493 | |
483 | 494 | # Populate parms.h, making the compilation environment known to Prolog |
67 | 67 | /* PLVERSION_TAG: a string, normally "", but for example "rc1" */ |
68 | 68 | |
69 | 69 | #ifndef PLVERSION |
70 | #define PLVERSION 80126 | |
70 | #define PLVERSION 80128 | |
71 | 71 | #endif |
72 | 72 | #ifndef PLVERSION_TAG |
73 | 73 | #define PLVERSION_TAG "" |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2009-2019, University of Amsterdam | |
5 | Copyright (c) 2009-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | CWI, Amsterdam |
8 | 8 | All rights reserved. |
38 | 38 | test_clause_gc/1 |
39 | 39 | ]). |
40 | 40 | |
41 | %% test_clause_gc | |
41 | %! test_clause_gc | |
42 | 42 | % |
43 | % This test runs a loop that builds a list and for each iteration | |
44 | % runs clause/2 on a term that contains all relevant programing | |
45 | % constructs. The idea is to trigger GC and shifts at different | |
46 | % parts of this process. | |
43 | % This test runs a loop that builds a list and for each iteration runs | |
44 | % clause/2 on a term that contains all relevant programing constructs. | |
45 | % The idea is to trigger GC and shifts at different parts of this | |
46 | % process. | |
47 | 47 | |
48 | 48 | test_clause_gc :- |
49 | setup_call_cleanup(( current_prolog_flag(stack_limit, SavedLimit), | |
50 | set_prolog_flag(stack_limit, 2_000_000), | |
51 | gspace(Cells), | |
52 | MaxLen is max(10000, (Cells//4)//3)), | |
53 | test_clause_gc(MaxLen), | |
54 | set_prolog_flag(stack_limit, SavedLimit)). | |
49 | setup_call_cleanup(( current_prolog_flag(stack_limit, SavedLimit), | |
50 | set_prolog_flag(stack_limit, 2_000_000), | |
51 | gspace(Cells), | |
52 | MaxLen is max(10000, (Cells//4)//3)), | |
53 | test_clause_gc(MaxLen), | |
54 | set_prolog_flag(stack_limit, SavedLimit)). | |
55 | 55 | |
56 | 56 | test_clause_gc(N) :- |
57 | run(N, L), | |
58 | is_list(L). % avoid L from being GC'ed | |
57 | catch(run(N, L), error(resource_error(stack), _), L=[]), | |
58 | is_list(L). % avoid L from being GC'ed | |
59 | 59 | |
60 | 60 | run(N, L) :- |
61 | functor(H, cl, 8), | |
62 | clause(H, B), | |
63 | run(N, H, B, L). | |
61 | functor(H, cl, 8), | |
62 | clause(H, B), | |
63 | run(N, H, B, L). | |
64 | 64 | |
65 | 65 | run(N, H, B, [x|L]) :- |
66 | succ(N2, N), !, | |
67 | functor(H2, cl, 8), | |
68 | clause(H2, B2), | |
69 | H =@= H2, | |
70 | B =@= B2, | |
71 | run(N2, H, B, L). | |
66 | succ(N2, N), !, | |
67 | functor(H2, cl, 8), | |
68 | clause(H2, B2), | |
69 | H =@= H2, | |
70 | B =@= B2, | |
71 | run(N2, H, B, L). | |
72 | 72 | run(_, _, _, []). |
73 | 73 | |
74 | 74 | :- dynamic cl/8. % make sure we can use clause/2 |
96 | 96 | *******************************/ |
97 | 97 | |
98 | 98 | gspace(Cells) :- |
99 | current_prolog_flag(stack_limit, Limit), | |
100 | statistics(globalused, Used), | |
101 | current_prolog_flag(address_bits, Wlen), | |
102 | Cells is (Limit-Used)//(Wlen//8). | |
99 | garbage_collect, | |
100 | current_prolog_flag(stack_limit, Limit), | |
101 | statistics(globalused, GUsed), | |
102 | statistics(localused, LUsed), | |
103 | statistics(trailused, TUsed), | |
104 | Used is GUsed+LUsed+TUsed, | |
105 | current_prolog_flag(address_bits, Wlen), | |
106 | Cells is (Limit-Used)//(Wlen//8). |
0 | /* Part of SWI-Prolog | |
1 | ||
2 | Author: Jan Wielemaker | |
3 | E-mail: J.Wielemaker@vu.nl | |
4 | WWW: http://www.swi-prolog.org | |
5 | Copyright (c) 2020, University of Amsterdam | |
6 | VU University Amsterdam | |
7 | CWI, Amsterdam | |
8 | All rights reserved. | |
9 | ||
10 | Redistribution and use in source and binary forms, with or without | |
11 | modification, are permitted provided that the following conditions | |
12 | are met: | |
13 | ||
14 | 1. Redistributions of source code must retain the above copyright | |
15 | notice, this list of conditions and the following disclaimer. | |
16 | ||
17 | 2. Redistributions in binary form must reproduce the above copyright | |
18 | notice, this list of conditions and the following disclaimer in | |
19 | the documentation and/or other materials provided with the | |
20 | distribution. | |
21 | ||
22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
23 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
25 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
26 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
27 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
28 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
30 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
31 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
32 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
33 | POSSIBILITY OF SUCH DAMAGE. | |
34 | */ | |
35 | ||
36 | :- module(test_thread_property, | |
37 | [ test_thread_property/0 | |
38 | ]). | |
39 | :- use_module(library(aggregate)). | |
40 | :- use_module(library(debug)). | |
41 | ||
42 | :- thread_local p/1, q/1. | |
43 | ||
44 | %! test_thread_property | |
45 | % | |
46 | % Tests asynchronous polling for thread properties while (notably) | |
47 | % threads terminate. Currently only checks the new size(Bytes) | |
48 | % property. | |
49 | ||
50 | test_thread_property :- | |
51 | test_thread_property(100). | |
52 | ||
53 | test_thread_property(N) :- | |
54 | thread_create(create_threads(N), Id, []), | |
55 | thread_create(poll_threads, Id2, []), | |
56 | thread_join(Id), | |
57 | thread_send_message(Id2, done), | |
58 | thread_join(Id2). | |
59 | ||
60 | create_threads(N) :- | |
61 | forall(between(1, N, _), | |
62 | ( thread_create(tmain, Id, [detached(true)]), | |
63 | catch(( thread_send_message(Id, hello(world)), | |
64 | thread_send_message(Id, done)), | |
65 | E, | |
66 | print_message(warning, E)), | |
67 | wait_drain | |
68 | )). | |
69 | ||
70 | wait_drain :- | |
71 | ( statistics(threads, N), | |
72 | N < 10 | |
73 | -> true | |
74 | ; sleep(0.01), | |
75 | wait_drain | |
76 | ). | |
77 | ||
78 | tmain :- | |
79 | forall(between(1, 100, I), | |
80 | ( assert(p(I)), | |
81 | assert(q(I)))). | |
82 | ||
83 | poll_threads :- | |
84 | thread_self(Me), | |
85 | thread_get_message(Me, done, [timeout(0)]), | |
86 | !. | |
87 | poll_threads :- | |
88 | aggregate_all(sum(S), | |
89 | thread_property(_, size(S)), | |
90 | Sum), | |
91 | debug(thread(size), 'Sum = ~D', [Sum]), | |
92 | poll_threads. | |
93 |
34 | 34 | :- module(thr_local_1, |
35 | 35 | [ thr_local_1/0 |
36 | 36 | ]). |
37 | :- use_module(library(apply)). | |
37 | 38 | |
38 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
39 | /** <module> Test thread local predicates | |
40 | ||
39 | 41 | This test validates the operation of thread-local dynamic predicates. It |
40 | creates 5 threads asserting the 1000 facts 1...1000 and checks they can | |
42 | creates 5 threads asserting the 1000 facts 1...1000 and checks they can | |
41 | 43 | be retracted in the proper order. |
42 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
44 | ||
45 | This test is a little overly complicated because a previous version was | |
46 | broken and we want to stay close to the previous example. One __can | |
47 | not__ to the following: | |
48 | ||
49 | - Create a thread using a `_` id (anonymous) and not detached and | |
50 | expects we can safely keep it running and join it by making the | |
51 | thread tell a join-thread that it is done. | |
52 | ||
53 | The reason for this is that atom-gc collects the handle and, if the | |
54 | thread still runs it _detaches_ it, so we can not join it. If it is | |
55 | already completed the garbage collector will join it, assuming that if | |
56 | nobody knows about this thread is it is safe the reclaim it. | |
57 | */ | |
43 | 58 | |
44 | 59 | :- thread_local |
45 | 60 | foo/1. |
48 | 63 | thr_local_1(5, 1000). |
49 | 64 | |
50 | 65 | thr_local_1(Threads, Asserts) :- |
66 | thread_create(acg_loop, Agc, []), | |
51 | 67 | thread_create(join(Threads), Id, []), |
52 | forall(between(1, Threads, _), | |
53 | thread_create(test_foo(Asserts), _, | |
54 | [ at_exit(done(Id)) | |
55 | ])), | |
56 | join_ok(Id). | |
68 | length(Ids, Threads), | |
69 | maplist(create_test_foo_thread(Asserts, Id), Ids), | |
70 | join_ok(Id), | |
71 | is_list(Ids), % avoid GC | |
72 | thread_send_message(Agc, done), | |
73 | join_ok(Agc). | |
74 | ||
75 | acg_loop :- | |
76 | garbage_collect_atoms, | |
77 | ( thread_peek_message(done) | |
78 | -> true | |
79 | ; sleep(0.001), | |
80 | acg_loop | |
81 | ). | |
57 | 82 | |
58 | 83 | join(Times) :- |
84 | thread_self(Me), | |
85 | debug(thread(local), 'Waiting thread = ~p', [Me]), | |
59 | 86 | forall(between(1, Times, _), |
60 | 87 | ( thread_get_message(done(Done)), |
61 | 88 | join_ok(Done) |
62 | 89 | )). |
63 | 90 | |
64 | 91 | join_ok(Id) :- |
92 | debug(thread(local), 'Joining ~p ...', [Id]), | |
65 | 93 | thread_join(Id, Return), |
94 | debug(thread(local), ' ... ~p', [Return]), | |
66 | 95 | ( Return == true |
67 | 96 | -> true |
68 | 97 | ; format('~N~p returned ~p~n', [Id, Return]), |
69 | 98 | fail |
70 | 99 | ). |
71 | 100 | |
101 | ||
102 | create_test_foo_thread(Asserts, ReportTo, Id) :- | |
103 | thread_create(test_foo(Asserts), Id, | |
104 | [ at_exit(done(ReportTo)) | |
105 | ]). | |
72 | 106 | |
73 | 107 | test_foo(N) :- |
74 | 108 | forall(between(0, N, X), |
112 | 146 | |
113 | 147 | done(Report) :- |
114 | 148 | thread_self(Me), |
149 | debug(thread(local), 'Signalling ~p that me (~p) is done', [Report, Me]), | |
115 | 150 | thread_send_message(Report, done(Me)). |
42 | 42 | % Similar to thread_agc_findall.pl, but without using findall. |
43 | 43 | |
44 | 44 | thread_agc :- |
45 | protocol(x), | |
46 | 45 | thread_agc(4, 10000). |
47 | 46 | |
48 | 47 | thread_agc(Threads, Count) :- |
215 | 215 | #cmakedefine HAVE_ZUTIL_H @HAVE_ZUTIL_H@ |
216 | 216 | #cmakedefine HAVE__BUILTIN_CLZ @HAVE__BUILTIN_CLZ@ |
217 | 217 | #cmakedefine HAVE__BUILTIN_POPCOUNT @HAVE__BUILTIN_POPCOUNT@ |
218 | #cmakedefine HAVE__SYNC_SYNCHRONIZE @HAVE__SYNC_SYNCHRONIZE@ | |
219 | #cmakedefine HAVE___SYNC_ADD_AND_FETCH_8 @HAVE___SYNC_ADD_AND_FETCH_8@ | |
218 | #cmakedefine HAVE_GCC_ATOMIC @HAVE_GCC_ATOMIC@ | |
219 | #cmakedefine HAVE_GCC_ATOMIC_8 @HAVE_GCC_ATOMIC_8@ | |
220 | 220 | #cmakedefine HAVE__NSGETENVIRON @HAVE__NSGETENVIRON@ |
221 | 221 | #cmakedefine LD_SYMBOL_PREFIX @LD_SYMBOL_PREFIX@ |
222 | 222 | #cmakedefine LINUX_CPUCLOCKS @LINUX_CPUCLOCKS@ |
265 | 265 | #cmakedefine VOID_UNSETENV @VOID_UNSETENV@ |
266 | 266 | #cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@ |
267 | 267 | #cmakedefine _LARGE_FILES @_LARGE_FILES@ |
268 | #cmakedefine _LARGEFILE_SOURCE @_LARGEFILE_SOURCE@ | |
268 | 269 | #cmakedefine _POSIX_PTHREAD_SEMANTICS @_POSIX_PTHREAD_SEMANTICS@ |
269 | 270 | #cmakedefine _THREAD_SAFE @_THREAD_SAFE@ |
270 | 271 | #cmakedefine inline @inline@ |
271 | 272 | #cmakedefine pid_t @pid_t@ |
272 | 273 | #cmakedefine size_t @size_t@ |
273 | 274 | #cmakedefine vfork @vfork@ |
275 | #cmakedefine HAVE_TCMALLOC_EXTENSION_C_H @HAVE_TCMALLOC_EXTENSION_C_H@ | |
274 | 276 | |
275 | 277 | #cmakedefine HAVE_PTHREAD_GETCPUCLOCKID |
276 | 278 | #cmakedefine HAVE_F_SETLKW |
48 | 48 | sz *= 2; |
49 | 49 | |
50 | 50 | if ( b->base == b->static_buffer ) |
51 | { if ( !(new = malloc(sz)) ) | |
51 | { sz = tmp_nalloc(sz); | |
52 | if ( !(new = tmp_malloc(sz)) ) | |
52 | 53 | return FALSE; |
53 | 54 | |
54 | 55 | memcpy(new, b->static_buffer, osz); |
55 | 56 | } else |
56 | { if ( !(new = realloc(b->base, sz)) ) | |
57 | { sz = tmp_nrealloc(b->base, sz); | |
58 | if ( !(new = tmp_realloc(b->base, sz)) ) | |
57 | 59 | return FALSE; |
58 | 60 | } |
59 | 61 | |
87 | 89 | |
88 | 90 | if ( !b->base ) |
89 | 91 | initBuffer(b); |
92 | else | |
93 | emptyBuffer(b); | |
90 | 94 | |
91 | emptyBuffer(b); | |
92 | 95 | return b; |
93 | 96 | } |
94 | 97 |
34 | 34 | #ifndef BUFFER_H_INCLUDED |
35 | 35 | #define BUFFER_H_INCLUDED |
36 | 36 | |
37 | #define STATIC_BUFFER_SIZE (512) | |
37 | #define STATIC_BUFFER_SIZE (512) | |
38 | #define BUFFER_DISCARD_ABOVE (4096) | |
38 | 39 | |
39 | 40 | typedef struct |
40 | 41 | { char * base; /* allocated base */ |
108 | 109 | #define initBuffer(b) ((b)->base = (b)->top = (b)->static_buffer, \ |
109 | 110 | (b)->max = (b)->base + \ |
110 | 111 | sizeof((b)->static_buffer)) |
111 | #define emptyBuffer(b) ((b)->top = (b)->base) | |
112 | #define emptyBuffer(b) emptyBuffer_((Buffer)(b), \ | |
113 | sizeof((b)->static_buffer)) | |
112 | 114 | #define isEmptyBuffer(b) ((b)->top == (b)->base) |
113 | 115 | #define popBuffer(b,type) \ |
114 | 116 | ((b)->top -= sizeof(type), *(type*)(b)->top) |
115 | 117 | #define popBufferP(b,type) \ |
116 | 118 | ((b)->top -= sizeof(type), (type*)(b)->top) |
119 | #define discardBuffer(b) discardBuffer_((Buffer)(b)) | |
117 | 120 | |
118 | #define discardBuffer(b) \ | |
119 | do \ | |
120 | { if ( (b)->base && (b)->base != (b)->static_buffer ) \ | |
121 | { free((b)->base); \ | |
122 | (b)->base = (b)->static_buffer; \ | |
123 | } \ | |
124 | } while(0) | |
121 | static inline void | |
122 | discardBuffer_(Buffer b) | |
123 | { if ( b->base && b->base != b->static_buffer ) | |
124 | tmp_free(b->base); | |
125 | } | |
125 | 126 | |
127 | static inline void | |
128 | emptyBuffer_(Buffer b, size_t emptysize) | |
129 | { if ( b->max - b->base < BUFFER_DISCARD_ABOVE ) | |
130 | { b->top = b->base; | |
131 | } else | |
132 | { discardBuffer(b); | |
133 | b->base = b->top = b->static_buffer, | |
134 | b->max = b->base + emptysize; | |
135 | } | |
136 | } | |
126 | 137 | |
127 | 138 | /******************************* |
128 | 139 | * FUNCTIONS * |
174 | 174 | ctx->alias_head = ctx->alias_tail = NULL; |
175 | 175 | ctx->filename = NULL_ATOM; |
176 | 176 | ctx->flags = 0; |
177 | if ( COMPARE_AND_SWAP(&s->context, NULL, ctx) ) | |
177 | if ( COMPARE_AND_SWAP_PTR(&s->context, NULL, ctx) ) | |
178 | 178 | addNewHTable(streamContext, s, ctx); |
179 | 179 | else |
180 | 180 | freeHeap(ctx, sizeof(*ctx)); |
284 | 284 | PL_LOCK(L_FILE); |
285 | 285 | unaliasStream(s, NULL_ATOM); |
286 | 286 | ctx = s->context; |
287 | if ( ctx && COMPARE_AND_SWAP(&s->context, ctx, NULL) ) | |
287 | if ( ctx && COMPARE_AND_SWAP_PTR(&s->context, ctx, NULL) ) | |
288 | 288 | { deleteHTable(streamContext, s); |
289 | 289 | if ( ctx->filename != NULL_ATOM ) |
290 | 290 | { PL_unregister_atom(ctx->filename); |
463 | 463 | } |
464 | 464 | #endif |
465 | 465 | |
466 | return 0; | |
466 | return heapUsed(); /* from pl-alloc.c */ | |
467 | 467 | } |
468 | 468 | |
469 | 469 | |
475 | 475 | struct rlimit limit; |
476 | 476 | |
477 | 477 | if ( getrlimit(RLIMIT_DATA, &limit) == 0 ) |
478 | return limit.rlim_cur - used; | |
478 | { if ( limit.rlim_cur == RLIM_INFINITY ) | |
479 | return (uintptr_t)-1; | |
480 | else | |
481 | return limit.rlim_cur - used; | |
482 | } | |
479 | 483 | #endif |
480 | 484 | |
481 | 485 | return 0L; |
914 | 914 | else if ( k == ATOM_shared_table_space ) |
915 | 915 | { if ( !GD->tabling.node_pool ) |
916 | 916 | { alloc_pool *pool = new_alloc_pool("shared_table_space", i); |
917 | if ( pool && !COMPARE_AND_SWAP(&GD->tabling.node_pool, NULL, pool) ) | |
917 | if ( pool && !COMPARE_AND_SWAP_PTR(&GD->tabling.node_pool, NULL, pool) ) | |
918 | 918 | free_alloc_pool(pool); |
919 | 919 | } else |
920 | 920 | GD->tabling.node_pool->limit = (size_t)i; |
1427 | 1427 | setPrologFlag("dialect", FT_ATOM|FF_READONLY, "swi"); |
1428 | 1428 | if ( systemDefaults.home ) |
1429 | 1429 | setPrologFlag("home", FT_ATOM|FF_READONLY, systemDefaults.home); |
1430 | #ifdef PLSHAREDHOME | |
1431 | setPrologFlag("shared_home", FT_ATOM|FF_READONLY, PLSHAREDHOME); | |
1432 | #endif | |
1430 | 1433 | if ( GD->paths.executable ) |
1431 | 1434 | setPrologFlag("executable", FT_ATOM|FF_READONLY, GD->paths.executable); |
1432 | 1435 | #if defined(HAVE_GETPID) || defined(EMULATE_GETPID) |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2017, University of Amsterdam | |
6 | VU University Amsterdam | |
7 | CWI, Amsterdam | |
5 | Copyright (c) 2017-2020, University of Amsterdam | |
6 | VU University Amsterdam | |
7 | CWI, Amsterdam | |
8 | 8 | All rights reserved. |
9 | 9 | |
10 | 10 | Redistribution and use in source and binary forms, with or without |
39 | 39 | #include "SWI-Stream.h" |
40 | 40 | |
41 | 41 | #ifdef O_PLMT |
42 | #define ATOMIC_ADD(ptr, v) __sync_add_and_fetch(ptr, v) | |
43 | #define ATOMIC_SUB(ptr, v) __sync_sub_and_fetch(ptr, v) | |
44 | #define ATOMIC_INC(ptr) ATOMIC_ADD(ptr, 1) /* ++(*ptr) */ | |
45 | #define ATOMIC_DEC(ptr) ATOMIC_SUB(ptr, 1) /* --(*ptr) */ | |
42 | #define ATOMIC_ADD(ptr, v) __atomic_add_fetch(ptr, v, __ATOMIC_SEQ_CST) | |
43 | #define ATOMIC_SUB(ptr, v) __atomic_sub_fetch(ptr, v, __ATOMIC_SEQ_CST) | |
44 | #define ATOMIC_INC(ptr) ATOMIC_ADD(ptr, 1) /* ++(*ptr) */ | |
45 | #define ATOMIC_DEC(ptr) ATOMIC_SUB(ptr, 1) /* --(*ptr) */ | |
46 | 46 | #else |
47 | #define ATOMIC_ADD(ptr, v) (*ptr += v) | |
48 | #define ATOMIC_SUB(ptr, v) (*ptr -= v) | |
49 | #define ATOMIC_INC(ptr) (++(*ptr)) | |
50 | #define ATOMIC_DEC(ptr) (--(*ptr)) | |
47 | #define ATOMIC_ADD(ptr, v) (*ptr += v) | |
48 | #define ATOMIC_SUB(ptr, v) (*ptr -= v) | |
49 | #define ATOMIC_INC(ptr) (++(*ptr)) | |
50 | #define ATOMIC_DEC(ptr) (--(*ptr)) | |
51 | 51 | #endif |
52 | 52 | |
53 | 53 |
118 | 118 | } |
119 | 119 | |
120 | 120 | static inline int htable_cas_name(KVS kvs, int idx, void *exp, void *name) |
121 | { return COMPARE_AND_SWAP(&kvs->entries[idx].name, exp, name); | |
121 | { return COMPARE_AND_SWAP_PTR(&kvs->entries[idx].name, exp, name); | |
122 | 122 | } |
123 | 123 | |
124 | 124 | static inline int htable_cas_value(KVS kvs, int idx, void *exp, void *value) |
125 | { return COMPARE_AND_SWAP(&kvs->entries[idx].value, exp, value); | |
125 | { return COMPARE_AND_SWAP_PTR(&kvs->entries[idx].value, exp, value); | |
126 | 126 | } |
127 | 127 | |
128 | 128 | static inline int htable_cas_new_kvs(KVS kvs, KVS new_kvs) |
129 | { return COMPARE_AND_SWAP(&kvs->next, NULL, new_kvs); | |
129 | { return COMPARE_AND_SWAP_PTR(&kvs->next, NULL, new_kvs); | |
130 | 130 | } |
131 | 131 | |
132 | 132 | static inline int htable_cas_cleanup(Table ht, int exp, int cleanup) |
133 | { return COMPARE_AND_SWAP(&ht->cleanup, exp, cleanup); | |
133 | { return COMPARE_AND_SWAP_INT(&ht->cleanup, exp, cleanup); | |
134 | 134 | } |
135 | 135 | |
136 | 136 |
0 | #define PLHOME "@PLHOME@" | |
1 | #define PLARCH "@PLARCH@" | |
2 | #define C_CC "@C_CC@" | |
3 | #define C_CXX "@C_CXX@" | |
4 | #define C_CFLAGS "@C_CFLAGS@" | |
5 | #cmakedefine SO_EXT "@SO_EXT@" | |
6 | #cmakedefine SO_PATH "@SO_PATH@" | |
7 | #cmakedefine C_LIBDIR "@SWIPL_RELATIVE_LIBDIR@" | |
8 | #cmakedefine C_LIBPLSO "@C_LIBPLSO@" | |
9 | #define C_LIBS "" | |
10 | #define C_PLLIB "-lswipl" | |
11 | #define C_LDFLAGS "" | |
0 | #define PLHOME "@PLHOME@" | |
1 | #cmakedefine PLSHAREDHOME "@PLSHAREDHOME@" | |
2 | #define PLARCH "@PLARCH@" | |
3 | #define C_CC "@C_CC@" | |
4 | #define C_CXX "@C_CXX@" | |
5 | #define C_CFLAGS "@C_CFLAGS@" | |
6 | #cmakedefine SO_EXT "@SO_EXT@" | |
7 | #cmakedefine SO_PATH "@SO_PATH@" | |
8 | #cmakedefine C_LIBDIR "@SWIPL_RELATIVE_LIBDIR@" | |
9 | #cmakedefine C_LIBPLSO "@C_LIBPLSO@" | |
10 | #define C_LIBS "" | |
11 | #define C_PLLIB "-lswipl" | |
12 | #define C_LDFLAGS "" |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1985-2018, University of Amsterdam | |
5 | Copyright (c) 1985-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | CWI, Amsterdam |
8 | 8 | All rights reserved. |
36 | 36 | #include "pl-incl.h" |
37 | 37 | #include "os/pl-cstack.h" |
38 | 38 | #include "pl-dict.h" |
39 | #ifdef HAVE_SYS_MMAN_H | |
40 | #define MMAP_STACK 1 | |
41 | #include <sys/mman.h> | |
42 | #include <unistd.h> | |
43 | #endif | |
39 | 44 | |
40 | 45 | #undef LD |
41 | 46 | #define LD LOCAL_LD |
199 | 204 | do |
200 | 205 | { o = *list; |
201 | 206 | c->next = o; |
202 | } while( !COMPARE_AND_SWAP(list, o, c) ); | |
207 | } while( !COMPARE_AND_SWAP_PTR(list, o, c) ); | |
203 | 208 | } |
204 | 209 | |
205 | 210 | void |
209 | 214 | |
210 | 215 | while ( c ) |
211 | 216 | { if ( c->generation < generation ) |
212 | { while ( !COMPARE_AND_SWAP(p, c, c->next) ) | |
217 | { while ( !COMPARE_AND_SWAP_PTR(p, c, c->next) ) | |
213 | 218 | { p = &(*p)->next; |
214 | 219 | } |
215 | 220 | (*c->unalloc)(c->object); |
715 | 720 | { Word *newbase; |
716 | 721 | size_t newsize = nextStackSize((Stack)&LD->stacks.argument, 1); |
717 | 722 | |
718 | if ( newsize && (newbase = stack_realloc(aBase, newsize)) ) | |
723 | if ( newsize && | |
724 | (newsize = stack_nalloc(newsize)) && | |
725 | (newbase = stack_realloc(aBase, newsize)) ) | |
719 | 726 | { intptr_t as = newbase - aBase; |
720 | 727 | |
721 | 728 | if ( as ) |
1374 | 1381 | initHBase(); |
1375 | 1382 | } |
1376 | 1383 | |
1384 | /******************************* | |
1385 | * MMAP STACKS * | |
1386 | *******************************/ | |
1387 | ||
1388 | #ifdef MMAP_STACK | |
1389 | #define MMAP_THRESHOLD 32768 | |
1390 | ||
1391 | typedef struct | |
1392 | { size_t size; /* Size (including header) */ | |
1393 | int mmapped; /* Is mmapped? */ | |
1394 | double data[1]; /* ensure alignment */ | |
1395 | } map_region; | |
1396 | ||
1397 | #define SA_OFFSET offsetof(map_region, data) | |
1398 | ||
1399 | static size_t | |
1400 | pgsize(void) | |
1401 | { static size_t sz = 0; | |
1402 | ||
1403 | if ( !sz ) | |
1404 | sz = sysconf(_SC_PAGESIZE); | |
1405 | ||
1406 | return sz; | |
1407 | } | |
1408 | ||
1409 | static inline size_t | |
1410 | roundpgsize(size_t sz) | |
1411 | { size_t r = pgsize(); | |
1412 | ||
1413 | return ((sz+r-1)/r)*r; | |
1414 | } | |
1415 | ||
1416 | size_t | |
1417 | tmp_nalloc(size_t req) | |
1418 | { if ( req < MMAP_THRESHOLD-SA_OFFSET ) | |
1419 | return req; | |
1420 | ||
1421 | return roundpgsize(req+SA_OFFSET)-SA_OFFSET; | |
1422 | } | |
1423 | ||
1424 | size_t | |
1425 | tmp_nrealloc(void *mem, size_t req) | |
1426 | { if ( mem ) | |
1427 | { map_region *reg = (map_region *)((char*)mem-SA_OFFSET); | |
1428 | ||
1429 | if ( !reg->mmapped && req < MMAP_THRESHOLD-SA_OFFSET ) | |
1430 | return req; | |
1431 | ||
1432 | return roundpgsize(req+SA_OFFSET)-SA_OFFSET; | |
1433 | } | |
1434 | ||
1435 | return tmp_nalloc(req); | |
1436 | } | |
1437 | ||
1438 | ||
1439 | size_t | |
1440 | tmp_malloc_size(void *mem) | |
1441 | { if ( mem ) | |
1442 | { map_region *reg = (map_region *)((char*)mem-SA_OFFSET); | |
1443 | return reg->size-SA_OFFSET; | |
1444 | } | |
1445 | ||
1446 | return 0; | |
1447 | } | |
1448 | ||
1449 | void * | |
1450 | tmp_malloc(size_t req) | |
1451 | { map_region *reg; | |
1452 | int mmapped; | |
1453 | ||
1454 | req += SA_OFFSET; | |
1455 | if ( req < MMAP_THRESHOLD ) | |
1456 | { reg = malloc(req); | |
1457 | mmapped = FALSE; | |
1458 | } else | |
1459 | { req = roundpgsize(req); | |
1460 | ||
1461 | reg = mmap(NULL, req, | |
1462 | (PROT_READ|PROT_WRITE), | |
1463 | (MAP_PRIVATE|MAP_ANONYMOUS), | |
1464 | -1, 0); | |
1465 | if ( reg == MAP_FAILED ) | |
1466 | reg = NULL; | |
1467 | mmapped = TRUE; | |
1468 | } | |
1469 | ||
1470 | if ( reg ) | |
1471 | { reg->size = req; | |
1472 | reg->mmapped = mmapped; | |
1473 | #ifdef O_DEBUG | |
1474 | memset(reg->data, 0xFB, req-SA_OFFSET); | |
1475 | #endif | |
1476 | ||
1477 | return reg->data; | |
1478 | } | |
1479 | ||
1480 | return NULL; | |
1481 | } | |
1482 | ||
1483 | ||
1484 | void * | |
1485 | tmp_realloc(void *mem, size_t req) | |
1486 | { if ( mem ) | |
1487 | { map_region *reg = (map_region *)((char*)mem-SA_OFFSET); | |
1488 | ||
1489 | req += SA_OFFSET; | |
1490 | if ( !reg->mmapped ) | |
1491 | { if ( req < MMAP_THRESHOLD ) | |
1492 | { map_region *nw = realloc(reg, req); | |
1493 | if ( nw ) | |
1494 | { nw->size = req; | |
1495 | return nw->data; | |
1496 | } | |
1497 | return NULL; | |
1498 | } else /* malloc --> mmap */ | |
1499 | { void *nw = tmp_malloc(req-SA_OFFSET); | |
1500 | if ( nw ) | |
1501 | { size_t copy = reg->size; | |
1502 | ||
1503 | if ( copy > req ) | |
1504 | copy = req; | |
1505 | ||
1506 | memcpy(nw, mem, copy-SA_OFFSET); | |
1507 | free(reg); | |
1508 | } | |
1509 | return nw; | |
1510 | } | |
1511 | } else | |
1512 | { req = roundpgsize(req); | |
1513 | ||
1514 | if ( reg->size != req ) | |
1515 | { if ( reg->size > req ) | |
1516 | { size_t trunk = reg->size-req; | |
1517 | ||
1518 | munmap((char*)reg+req, trunk); | |
1519 | reg->size = req; | |
1520 | ||
1521 | return reg->data; | |
1522 | } else | |
1523 | { void *ra = tmp_malloc(req); | |
1524 | ||
1525 | if ( ra ) | |
1526 | { memcpy(ra, mem, reg->size-SA_OFFSET); | |
1527 | #ifdef O_DEBUG | |
1528 | memset((char*)ra+reg->size-SA_OFFSET, 0xFB, | |
1529 | req-(reg->size-SA_OFFSET)); | |
1530 | #endif | |
1531 | tmp_free(mem); | |
1532 | } | |
1533 | ||
1534 | return ra; | |
1535 | } | |
1536 | } else | |
1537 | { return mem; | |
1538 | } | |
1539 | } | |
1540 | } else | |
1541 | { return tmp_malloc(req); | |
1542 | } | |
1543 | } | |
1544 | ||
1545 | ||
1546 | void | |
1547 | tmp_free(void *mem) | |
1548 | { if ( mem ) | |
1549 | { map_region *reg = (map_region *)((char*)mem-SA_OFFSET); | |
1550 | ||
1551 | if ( reg->mmapped ) | |
1552 | munmap(reg, reg->size); | |
1553 | else | |
1554 | free(reg); | |
1555 | } | |
1556 | } | |
1557 | ||
1558 | #else /*MMAP_STACK*/ | |
1559 | ||
1560 | size_t | |
1561 | tmp_nalloc(size_t req) | |
1562 | { return req; | |
1563 | } | |
1564 | ||
1565 | size_t | |
1566 | tmp_nrealloc(void *mem, size_t req) | |
1567 | { (void)mem; | |
1568 | ||
1569 | return req; | |
1570 | } | |
1571 | ||
1572 | size_t | |
1573 | tmp_malloc_size(void *mem) | |
1574 | { if ( mem ) | |
1575 | { size_t *sp = mem; | |
1576 | return sp[-1]; | |
1577 | } | |
1578 | ||
1579 | return 0; | |
1580 | } | |
1581 | ||
1582 | void * | |
1583 | tmp_malloc(size_t size) | |
1584 | { void *mem = malloc(size+sizeof(size_t)); | |
1585 | ||
1586 | if ( mem ) | |
1587 | { size_t *sp = mem; | |
1588 | *sp++ = size; | |
1589 | #ifdef O_DEBUG | |
1590 | memset(sp, 0xFB, size); | |
1591 | #endif | |
1592 | ||
1593 | return sp; | |
1594 | } | |
1595 | ||
1596 | return NULL; | |
1597 | } | |
1598 | ||
1599 | void * | |
1600 | tmp_realloc(void *old, size_t size) | |
1601 | { size_t *sp = old; | |
1602 | size_t osize = *--sp; | |
1603 | void *mem; | |
1604 | ||
1605 | #ifdef O_DEBUG | |
1606 | if ( (mem = tmp_malloc(size)) ) | |
1607 | { memcpy(mem, old, (size>osize?osize:size)); | |
1608 | tmp_free(old); | |
1609 | return mem; | |
1610 | } | |
1611 | #else | |
1612 | (void)osize; | |
1613 | if ( (mem = realloc(sp, size+sizeof(size_t))) ) | |
1614 | { sp = mem; | |
1615 | *sp++ = size; | |
1616 | return sp; | |
1617 | } | |
1618 | #endif | |
1619 | ||
1620 | return NULL; | |
1621 | } | |
1622 | ||
1623 | void | |
1624 | tmp_free(void *mem) | |
1625 | { size_t *sp = mem; | |
1626 | size_t osize = *--sp; | |
1627 | ||
1628 | #ifdef O_DEBUG | |
1629 | memset(sp, 0xFB, osize+sizeof(size_t)); | |
1630 | #else | |
1631 | (void)osize; | |
1632 | #endif | |
1633 | free(sp); | |
1634 | } | |
1635 | ||
1636 | #endif /*MMAP_STACK*/ | |
1637 | ||
1638 | void * | |
1639 | stack_malloc(size_t size) | |
1640 | { void *ptr = tmp_malloc(size); | |
1641 | ||
1642 | if ( ptr ) | |
1643 | ATOMIC_ADD(&GD->statistics.stack_space, tmp_malloc_size(ptr)); | |
1644 | ||
1645 | return ptr; | |
1646 | } | |
1647 | ||
1648 | void * | |
1649 | stack_realloc(void *mem, size_t size) | |
1650 | { size_t osize = tmp_malloc_size(mem); | |
1651 | void *ptr = tmp_realloc(mem, size); | |
1652 | ||
1653 | if ( ptr ) | |
1654 | { size = tmp_malloc_size(ptr); | |
1655 | ||
1656 | if ( osize > size ) | |
1657 | ATOMIC_SUB(&GD->statistics.stack_space, osize-size); | |
1658 | else | |
1659 | ATOMIC_ADD(&GD->statistics.stack_space, size-osize); | |
1660 | } | |
1661 | ||
1662 | return ptr; | |
1663 | } | |
1664 | ||
1665 | void | |
1666 | stack_free(void *mem) | |
1667 | { size_t size = tmp_malloc_size(mem); | |
1668 | ||
1669 | ATOMIC_SUB(&GD->statistics.stack_space, size); | |
1670 | tmp_free(mem); | |
1671 | } | |
1672 | ||
1673 | size_t | |
1674 | stack_nalloc(size_t req) | |
1675 | { return tmp_nalloc(req); | |
1676 | } | |
1677 | ||
1678 | size_t | |
1679 | stack_nrealloc(void *mem, size_t req) | |
1680 | { return tmp_nrealloc(mem, req); | |
1681 | } | |
1682 | ||
1683 | ||
1684 | /******************************* | |
1685 | * TCMALLOC * | |
1686 | *******************************/ | |
1687 | ||
1688 | static int (*fMallocExtension_GetNumericProperty)(const char *, size_t *); | |
1689 | static int (*fMallocExtension_SetNumericProperty)(const char *, size_t); | |
1690 | static void (*fMallocExtension_MarkThreadIdle)(void) = NULL; | |
1691 | static void (*fMallocExtension_MarkThreadTemporarilyIdle)(void) = NULL; | |
1692 | static void (*fMallocExtension_MarkThreadBusy)(void) = NULL; | |
1693 | ||
1694 | static const char* tcmalloc_properties[] = | |
1695 | { "generic.current_allocated_bytes", | |
1696 | "generic.heap_size", | |
1697 | "tcmalloc.max_total_thread_cache_bytes", | |
1698 | "tcmalloc.current_total_thread_cache_bytes", | |
1699 | "tcmalloc.central_cache_free_bytes", | |
1700 | "tcmalloc.transfer_cache_free_bytes", | |
1701 | "tcmalloc.thread_cache_free_bytes", | |
1702 | "tcmalloc.pageheap_free_bytes", | |
1703 | "tcmalloc.pageheap_unmapped_bytes", | |
1704 | NULL | |
1705 | }; | |
1706 | ||
1707 | static foreign_t | |
1708 | malloc_property(term_t prop, control_t handle) | |
1709 | { GET_LD | |
1710 | const char **pname; | |
1711 | ||
1712 | switch( PL_foreign_control(handle) ) | |
1713 | { case PL_FIRST_CALL: | |
1714 | { atom_t name; | |
1715 | size_t arity; | |
1716 | ||
1717 | if ( PL_get_name_arity(prop, &name, &arity) && arity == 1 ) | |
1718 | { const char *s = PL_atom_nchars(name, NULL); | |
1719 | ||
1720 | if ( s ) | |
1721 | { pname = tcmalloc_properties; | |
1722 | ||
1723 | for(; *pname; pname++) | |
1724 | { if ( streq(s, *pname) ) | |
1725 | { size_t val; | |
1726 | ||
1727 | if ( fMallocExtension_GetNumericProperty(*pname, &val) ) | |
1728 | { term_t a = PL_new_term_ref(); | |
1729 | _PL_get_arg(1, prop, a); | |
1730 | return PL_unify_uint64(a, val); | |
1731 | } | |
1732 | } | |
1733 | } | |
1734 | } | |
1735 | ||
1736 | return FALSE; | |
1737 | } else if ( PL_is_variable(prop) ) | |
1738 | { pname = tcmalloc_properties; | |
1739 | goto enumerate; | |
1740 | } | |
1741 | } | |
1742 | case PL_REDO: | |
1743 | { fid_t fid; | |
1744 | ||
1745 | pname = PL_foreign_context_address(handle); | |
1746 | enumerate: | |
1747 | ||
1748 | fid = PL_open_foreign_frame(); | |
1749 | for(; *pname; pname++) | |
1750 | { size_t val; | |
1751 | ||
1752 | if ( fMallocExtension_GetNumericProperty(*pname, &val) ) | |
1753 | { if ( PL_unify_term(prop, PL_FUNCTOR_CHARS, *pname, 1, | |
1754 | PL_INT64, val) ) | |
1755 | { PL_close_foreign_frame(fid); | |
1756 | pname++; | |
1757 | if ( *pname ) | |
1758 | PL_retry_address(pname); | |
1759 | else | |
1760 | return TRUE; | |
1761 | } | |
1762 | } | |
1763 | ||
1764 | if ( PL_exception(0) ) | |
1765 | return FALSE; | |
1766 | PL_rewind_foreign_frame(fid); | |
1767 | } | |
1768 | PL_close_foreign_frame(fid); | |
1769 | ||
1770 | return FALSE; | |
1771 | } | |
1772 | case PL_CUTTED: | |
1773 | { return TRUE; | |
1774 | } | |
1775 | default: | |
1776 | { assert(0); | |
1777 | return FALSE; | |
1778 | } | |
1779 | } | |
1780 | } | |
1781 | ||
1782 | static foreign_t | |
1783 | set_malloc(term_t prop) | |
1784 | { GET_LD | |
1785 | atom_t name; | |
1786 | size_t arity; | |
1787 | ||
1788 | if ( PL_get_name_arity(prop, &name, &arity) && arity == 1 ) | |
1789 | { const char *s = PL_atom_nchars(name, NULL); | |
1790 | term_t a = PL_new_term_ref(); | |
1791 | size_t val; | |
1792 | ||
1793 | if ( !PL_get_arg(1, prop, a) || | |
1794 | !PL_get_size_ex(a, &val) ) | |
1795 | return FALSE; | |
1796 | ||
1797 | if ( s ) | |
1798 | { const char **pname = tcmalloc_properties; | |
1799 | ||
1800 | for(; *pname; pname++) | |
1801 | { if ( streq(s, *pname) ) | |
1802 | { if ( fMallocExtension_SetNumericProperty(*pname, val) ) | |
1803 | return TRUE; | |
1804 | else | |
1805 | return PL_permission_error("set", "malloc_property", prop); | |
1806 | } | |
1807 | } | |
1808 | ||
1809 | return PL_domain_error("malloc_property", prop); | |
1810 | } | |
1811 | } | |
1812 | ||
1813 | return PL_type_error("malloc_property", prop); | |
1814 | } | |
1815 | ||
1816 | ||
1817 | size_t | |
1818 | heapUsed(void) | |
1819 | { size_t val; | |
1820 | ||
1821 | if (fMallocExtension_GetNumericProperty && | |
1822 | fMallocExtension_GetNumericProperty("generic.current_allocated_bytes", &val)) | |
1823 | { | |
1824 | #ifdef MMAP_STACK | |
1825 | val += GD->statistics.stack_space; | |
1826 | #endif | |
1827 | ||
1828 | return val; | |
1829 | } | |
1830 | ||
1831 | return 0; | |
1832 | } | |
1833 | ||
1834 | ||
1835 | int | |
1836 | initTCMalloc(void) | |
1837 | { static int done = FALSE; | |
1838 | int set = 0; | |
1839 | ||
1840 | if ( done ) | |
1841 | return !!fMallocExtension_GetNumericProperty; | |
1842 | done = TRUE; | |
1843 | ||
1844 | if ( (fMallocExtension_GetNumericProperty = | |
1845 | PL_dlsym(NULL, "MallocExtension_GetNumericProperty")) ) | |
1846 | { PL_register_foreign_in_module("system", "malloc_property", 1, malloc_property, | |
1847 | PL_FA_NONDETERMINISTIC); | |
1848 | set++; | |
1849 | } | |
1850 | if ( (fMallocExtension_SetNumericProperty = | |
1851 | PL_dlsym(NULL, "MallocExtension_SetNumericProperty")) ) | |
1852 | { PL_register_foreign_in_module("system", "set_malloc", 1, set_malloc, 0); | |
1853 | set++; | |
1854 | } | |
1855 | ||
1856 | fMallocExtension_MarkThreadIdle = | |
1857 | PL_dlsym(NULL, "MallocExtension_MarkThreadIdle"); | |
1858 | fMallocExtension_MarkThreadTemporarilyIdle = | |
1859 | PL_dlsym(NULL, "MallocExtension_MarkThreadTemporarilyIdle"); | |
1860 | fMallocExtension_MarkThreadBusy = | |
1861 | PL_dlsym(NULL, "MallocExtension_MarkThreadBusy"); | |
1862 | ||
1863 | return set; | |
1864 | } | |
1865 | ||
1866 | ||
1867 | /** thread_idle(:Goal, +How) | |
1868 | * | |
1869 | */ | |
1870 | ||
1871 | static | |
1872 | PRED_IMPL("thread_idle", 2, thread_idle, PL_FA_TRANSPARENT) | |
1873 | { PRED_LD | |
1874 | int rc; | |
1875 | atom_t how; | |
1876 | ||
1877 | if ( !PL_get_atom_ex(A2, &how) ) | |
1878 | return FALSE; | |
1879 | ||
1880 | if ( how == ATOM_short ) | |
1881 | { trimStacks(TRUE PASS_LD); | |
1882 | if ( fMallocExtension_MarkThreadTemporarilyIdle && | |
1883 | fMallocExtension_MarkThreadBusy ) | |
1884 | fMallocExtension_MarkThreadTemporarilyIdle(); | |
1885 | } else if ( how == ATOM_long ) | |
1886 | { LD->trim_stack_requested = TRUE; | |
1887 | garbageCollect(GC_USER); | |
1888 | LD->trim_stack_requested = FALSE; | |
1889 | if ( fMallocExtension_MarkThreadIdle && | |
1890 | fMallocExtension_MarkThreadBusy ) | |
1891 | fMallocExtension_MarkThreadIdle(); | |
1892 | } | |
1893 | ||
1894 | rc = callProlog(NULL, A1, PL_Q_PASS_EXCEPTION, NULL); | |
1895 | ||
1896 | if ( fMallocExtension_MarkThreadBusy ) | |
1897 | fMallocExtension_MarkThreadBusy(); | |
1898 | ||
1899 | return rc; | |
1900 | } | |
1901 | ||
1902 | ||
1377 | 1903 | |
1378 | 1904 | /******************************* |
1379 | 1905 | * PREDICATES * |
1392 | 1918 | #ifdef HAVE_BOEHM_GC |
1393 | 1919 | PRED_DEF("garbage_collect_heap", 0, garbage_collect_heap, 0) |
1394 | 1920 | #endif |
1921 | PRED_DEF("thread_idle", 2, thread_idle, PL_FA_TRANSPARENT) | |
1395 | 1922 | EndPredDefs |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2012-2018, VU University Amsterdam | |
5 | Copyright (c) 2012-2020, VU University Amsterdam | |
6 | 6 | CWI, Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
90 | 90 | *******************************/ |
91 | 91 | |
92 | 92 | COMMON(void) initAlloc(void); |
93 | COMMON(int) initTCMalloc(void); | |
94 | COMMON(size_t) heapUsed(void); | |
93 | 95 | #ifndef DMALLOC |
94 | 96 | COMMON(void *) allocHeap(size_t n); |
95 | 97 | COMMON(void *) allocHeapOrHalt(size_t n); |
118 | 120 | COMMON(int) equalIndirect(word r1, word r2); |
119 | 121 | COMMON(size_t) gsizeIndirectFromCode(Code PC); |
120 | 122 | COMMON(word) globalIndirectFromCode(Code *PC); |
123 | COMMON(void *) tmp_malloc(size_t req); | |
124 | COMMON(void *) tmp_realloc(void *mem, size_t req); | |
125 | COMMON(void) tmp_free(void *mem); | |
126 | COMMON(size_t) tmp_nalloc(size_t req); | |
127 | COMMON(size_t) tmp_nrealloc(void *mem, size_t req); | |
128 | COMMON(void *) stack_malloc(size_t req); | |
129 | COMMON(void *) stack_realloc(void *mem, size_t req); | |
130 | COMMON(void) stack_free(void *mem); | |
131 | COMMON(size_t) stack_nalloc(size_t req); | |
132 | COMMON(size_t) stack_nrealloc(void *mem, size_t req); | |
121 | 133 | #ifndef xmalloc |
122 | 134 | COMMON(void *) xmalloc(size_t size); |
123 | 135 | COMMON(void *) xrealloc(void *mem, size_t size); |
2063 | 2063 | { exp_nan = FALSE; |
2064 | 2064 | exp_sign = ar_sign_i(n2); |
2065 | 2065 | } |
2066 | r->type = V_INTEGER; // for all special cases | |
2066 | r->type = V_INTEGER; /* for all special cases */ | |
2067 | 2067 | |
2068 | 2068 | if ( exp_sign == 0 && !exp_nan ) /* test for X**0 */ |
2069 | 2069 | { r->value.i = 1; |
2214 | 2214 | if ( mpz_sgn(r->value.mpz) == -1 && !(r_den & 1)) |
2215 | 2215 | { mpz_clear(r->value.mpz); |
2216 | 2216 | r->type = V_FLOAT; |
2217 | r->value.f = NAN; | |
2217 | r->value.f = const_nan; | |
2218 | 2218 | return check_float(r); |
2219 | 2219 | } |
2220 | 2220 | |
2264 | 2264 | if ( (mpq_sgn(r->value.mpq) == -1 ) && !(r_den & 1)) |
2265 | 2265 | { mpq_clear(r->value.mpq); |
2266 | 2266 | r->type = V_FLOAT; |
2267 | r->value.f = NAN; | |
2267 | r->value.f = const_nan; | |
2268 | 2268 | return check_float(r); |
2269 | 2269 | } |
2270 | 2270 | |
2294 | 2294 | assert(0); |
2295 | 2295 | } |
2296 | 2296 | case V_FLOAT: |
2297 | { if ( n1->value.f == 0.0 ) goto doreal; // general case of 0.0**X | |
2297 | { if ( n1->value.f == 0.0 ) goto doreal; /* general case of 0.0**X */ | |
2298 | 2298 | if ( n1->value.f < 0 && !( r_den & 1 )) |
2299 | { r->value.f = NAN; /* negative base, even denominator */ | |
2299 | { r->value.f = const_nan; /* negative base, even denominator */ | |
2300 | 2300 | } else |
2301 | 2301 | { |
2302 | 2302 | doreal_mpq: |
2332 | 2332 | |
2333 | 2333 | if ( n1->value.f == 0.0 && exp_sign == -1 ) |
2334 | 2334 | return check_zero_div(zero_div_sign, r, "**", 2); |
2335 | ||
2336 | r->value.f = pow(n1->value.f, n2->value.f); | |
2335 | if ( n1->value.f == 1.0 ) | |
2336 | r->value.f = 1.0; /* broken on e.g., mipsel */ | |
2337 | else | |
2338 | r->value.f = pow(n1->value.f, n2->value.f); | |
2337 | 2339 | r->type = V_FLOAT; |
2338 | 2340 | |
2339 | 2341 | return check_float(r); |
2709 | 2711 | { r->value.f = nexttoward(n1->value.f, n2->value.f); |
2710 | 2712 | r->type = V_FLOAT; |
2711 | 2713 | |
2712 | return TRUE; | |
2714 | return check_float(r); | |
2713 | 2715 | } |
2714 | 2716 | } |
2715 | 2717 | |
3756 | 3758 | |
3757 | 3759 | r->value.f = modf(n1->value.f, &ip); |
3758 | 3760 | r->type = V_FLOAT; |
3759 | } | |
3760 | } | |
3761 | ||
3762 | succeed; | |
3761 | return check_float(r); | |
3762 | } | |
3763 | default: | |
3764 | assert(0); | |
3765 | return FALSE; | |
3766 | } | |
3763 | 3767 | } |
3764 | 3768 | |
3765 | 3769 | |
3787 | 3791 | (void)modf(n1->value.f, &ip); |
3788 | 3792 | r->value.f = ip; |
3789 | 3793 | r->type = V_FLOAT; |
3790 | succeed; | |
3794 | return check_float(r); | |
3791 | 3795 | } |
3792 | 3796 | } |
3793 | 3797 | |
4434 | 4438 | |
4435 | 4439 | static atom_t float_rounding_names[5] = {0}; |
4436 | 4440 | |
4441 | static double | |
4442 | nan15(void) | |
4443 | { number n; | |
4444 | unsigned char *end; | |
4445 | ||
4446 | if ( str_number((const unsigned char *)"1.5NaN", &end, &n, 0) == NUM_OK ) | |
4447 | { assert(isnan(n.value.f)); | |
4448 | return n.value.f; | |
4449 | } else | |
4450 | { assert(0); | |
4451 | return NAN; | |
4452 | } | |
4453 | } | |
4454 | ||
4455 | ||
4437 | 4456 | void |
4438 | 4457 | initArith(void) |
4439 | 4458 | { GET_LD |
4443 | 4462 | fpsetmask(fpgetmask() & ~(FP_X_DZ|FP_X_INV|FP_X_OFL)); |
4444 | 4463 | #endif |
4445 | 4464 | |
4446 | const_nan = strtod("NaN", NULL); | |
4447 | const_inf = strtod("Inf", NULL); | |
4448 | const_neg_inf = strtod("-Inf", NULL); | |
4465 | const_nan = nan15(); | |
4466 | const_inf = HUGE_VAL; | |
4467 | const_neg_inf = -HUGE_VAL; | |
4449 | 4468 | |
4450 | 4469 | #ifdef O_GMP |
4451 | 4470 | LD->arith.rat.max_rational_size = (size_t)-1; |
212 | 212 | if ( ATOM_REF_COUNT(nref) == 0 ) |
213 | 213 | return TRUE; /* reached max references */ |
214 | 214 | |
215 | if ( COMPARE_AND_SWAP(&a->references, ref, nref) ) | |
215 | if ( COMPARE_AND_SWAP_UINT(&a->references, ref, nref) ) | |
216 | 216 | { if ( ATOM_REF_COUNT(ref) == 0 ) |
217 | 217 | ATOMIC_DEC(&GD->atoms.unregistered); |
218 | 218 | return TRUE; |
421 | 421 | { newblock[i].type = ATOM_TYPE_INVALID; |
422 | 422 | newblock[i].name = "<virgin>"; |
423 | 423 | } |
424 | if ( !COMPARE_AND_SWAP(&GD->atoms.array.blocks[idx], | |
424 | if ( !COMPARE_AND_SWAP_PTR(&GD->atoms.array.blocks[idx], | |
425 | 425 | NULL, newblock-bs) ) |
426 | 426 | PL_free(newblock); /* done by someone else */ |
427 | 427 | } |
452 | 452 | ref = a->references; |
453 | 453 | |
454 | 454 | if ( ATOM_IS_FREE(ref) && |
455 | COMPARE_AND_SWAP(&a->references, ref, ATOM_RESERVED_REFERENCE) ) | |
455 | COMPARE_AND_SWAP_UINT(&a->references, ref, ATOM_RESERVED_REFERENCE) ) | |
456 | 456 | { assert(a->type == ATOM_TYPE_INVALID); |
457 | 457 | GD->atoms.no_hole_before = index+1; |
458 | 458 | a->atom = (index<<LMASK_BITS)|TAG_ATOM; |
476 | 476 | ref = a->references; |
477 | 477 | |
478 | 478 | if ( ATOM_IS_FREE(ref) && |
479 | COMPARE_AND_SWAP(&a->references, ref, ATOM_RESERVED_REFERENCE) ) | |
480 | { COMPARE_AND_SWAP(&GD->atoms.highest, index, index+1); | |
479 | COMPARE_AND_SWAP_UINT(&a->references, ref, ATOM_RESERVED_REFERENCE) ) | |
480 | { COMPARE_AND_SWAP_SIZE(&GD->atoms.highest, index, index+1); | |
481 | 481 | a->atom = (index<<LMASK_BITS)|TAG_ATOM; |
482 | 482 | |
483 | 483 | return a; |
610 | 610 | if ( true(type, PL_BLOB_UNIQUE) ) |
611 | 611 | { a->next = table[v]; |
612 | 612 | if ( !( !GD->atoms.rehashing && /* See (**) above */ |
613 | COMPARE_AND_SWAP(&table[v], head, a) && | |
613 | COMPARE_AND_SWAP_PTR(&table[v], head, a) && | |
614 | 614 | table == GD->atoms.table->table ) ) |
615 | 615 | { if ( false(type, PL_BLOB_NOCOPY) ) |
616 | 616 | PL_free(a->name); |
827 | 827 | #define ATOM_PRE_DESTROY_REFERENCE \ |
828 | 828 | (ATOM_DESTROY_REFERENCE|ATOM_RESERVED_REFERENCE) |
829 | 829 | |
830 | if ( !COMPARE_AND_SWAP(&a->references, ref, ATOM_PRE_DESTROY_REFERENCE) ) | |
830 | if ( !COMPARE_AND_SWAP_UINT(&a->references, ref, ATOM_PRE_DESTROY_REFERENCE) ) | |
831 | 831 | { return FALSE; |
832 | 832 | } |
833 | 833 | |
834 | 834 | if ( a->type->release ) |
835 | 835 | { if ( !(*a->type->release)(a->atom) ) |
836 | { COMPARE_AND_SWAP(&a->references, ATOM_PRE_DESTROY_REFERENCE, ref); | |
836 | { COMPARE_AND_SWAP_UINT(&a->references, ATOM_PRE_DESTROY_REFERENCE, ref); | |
837 | 837 | return FALSE; |
838 | 838 | } |
839 | 839 | } else if ( GD->atoms.gc_hook ) |
840 | 840 | { if ( !(*GD->atoms.gc_hook)(a->atom) ) |
841 | { COMPARE_AND_SWAP(&a->references, ATOM_PRE_DESTROY_REFERENCE, ref); | |
841 | { COMPARE_AND_SWAP_UINT(&a->references, ATOM_PRE_DESTROY_REFERENCE, ref); | |
842 | 842 | return FALSE; /* foreign hooks says `no' */ |
843 | 843 | } |
844 | 844 | } |
860 | 860 | ap = &table->table[a->hash_value & mask]; |
861 | 861 | |
862 | 862 | if ( *ap == a ) |
863 | { if ( !COMPARE_AND_SWAP(&table->table[a->hash_value & mask], a, a->next) ) | |
863 | { if ( !COMPARE_AND_SWAP_PTR(&table->table[a->hash_value & mask], a, a->next) ) | |
864 | 864 | { goto redo; |
865 | 865 | } |
866 | 866 | } |
1020 | 1020 | if ( GD->cleaning != CLN_NORMAL ) /* Cleaning up */ |
1021 | 1021 | return TRUE; |
1022 | 1022 | |
1023 | if ( !COMPARE_AND_SWAP(&GD->atoms.gc_active, FALSE, TRUE) ) | |
1023 | if ( !COMPARE_AND_SWAP_INT(&GD->atoms.gc_active, FALSE, TRUE) ) | |
1024 | 1024 | return TRUE; |
1025 | 1025 | |
1026 | 1026 | if ( verbose ) |
1109 | 1109 | unsigned int nref = ref+1; |
1110 | 1110 | |
1111 | 1111 | if ( ATOM_REF_COUNT(nref) != 0 ) |
1112 | { if ( COMPARE_AND_SWAP(&p->references, ref, nref) ) | |
1112 | { if ( COMPARE_AND_SWAP_UINT(&p->references, ref, nref) ) | |
1113 | 1113 | { if ( ATOM_REF_COUNT(nref) == 1 ) |
1114 | 1114 | ATOMIC_DEC(&GD->atoms.unregistered); |
1115 | 1115 | return nref; |
1208 | 1208 | |
1209 | 1209 | if ( ATOM_REF_COUNT(newref) == 0 ) |
1210 | 1210 | newref |= ATOM_MARKED_REFERENCE; |
1211 | } while( !COMPARE_AND_SWAP(&p->references, oldref, newref) ); | |
1211 | } while( !COMPARE_AND_SWAP_UINT(&p->references, oldref, newref) ); | |
1212 | 1212 | refs = ATOM_REF_COUNT(newref); |
1213 | 1213 | #ifdef O_DEBUG_ATOMGC |
1214 | 1214 | if ( refs == 0 && atomLogFd && tracking(p) ) |
1505 | 1505 | size_t index; |
1506 | 1506 | int idx; |
1507 | 1507 | |
1508 | GD->atoms.builtin_array = PL_malloc(size * sizeof(struct atom)); | |
1509 | 1508 | GD->statistics.atoms = size; |
1510 | 1509 | |
1511 | 1510 | for( sp = atoms, index = GD->atoms.highest; *sp; sp++, index++ ) |
2173 | 2172 | } |
2174 | 2173 | |
2175 | 2174 | |
2175 | size_t | |
2176 | atom_space(void) | |
2177 | { size_t array = ((size_t)2<<MSB(GD->atoms.highest))*sizeof(struct atom); | |
2178 | size_t index; | |
2179 | int i, last=FALSE; | |
2180 | size_t table = GD->atoms.table->buckets * sizeof(Atom); | |
2181 | size_t data = 0; | |
2182 | ||
2183 | for(index=1, i=0; !last; i++) | |
2184 | { size_t upto = (size_t)2<<i; | |
2185 | size_t high = GD->atoms.highest; | |
2186 | Atom b = GD->atoms.array.blocks[i]; | |
2187 | ||
2188 | if ( upto >= high ) | |
2189 | { upto = high; | |
2190 | last = TRUE; | |
2191 | } | |
2192 | ||
2193 | for(; index<upto; index++) | |
2194 | { Atom a = b + index; | |
2195 | ||
2196 | if ( ATOM_IS_VALID(a->references) ) | |
2197 | { data += a->length; /* TBD: malloc rounding? */ | |
2198 | } | |
2199 | } | |
2200 | } | |
2201 | ||
2202 | return array+table+data; | |
2203 | } | |
2204 | ||
2205 | ||
2176 | 2206 | /******************************* |
2177 | 2207 | * PUBLISH PREDICATES * |
2178 | 2208 | *******************************/ |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1985-2014, University of Amsterdam | |
5 | Copyright (c) 1985-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | CWI Amsterdam | |
7 | 8 | All rights reserved. |
8 | 9 | |
9 | 10 | Redistribution and use in source and binary forms, with or without |
50 | 51 | findall/3. |
51 | 52 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
52 | 53 | |
53 | #define FIRST_CHUNK_SIZE (64*sizeof(void*)) | |
54 | #define FIRST_CHUNK_SIZE (256*sizeof(void*)) | |
54 | 55 | |
55 | 56 | typedef struct mem_chunk |
56 | 57 | { struct mem_chunk *prev; |
60 | 61 | |
61 | 62 | typedef struct mem_pool |
62 | 63 | { mem_chunk *chunks; |
64 | size_t chunk_count; | |
63 | 65 | mem_chunk first; |
64 | 66 | char first_data[FIRST_CHUNK_SIZE]; |
65 | 67 | } mem_pool; |
66 | 68 | |
67 | 69 | static void |
68 | 70 | init_mem_pool(mem_pool *mp) |
69 | { mp->chunks = &mp->first; | |
70 | mp->first.size = FIRST_CHUNK_SIZE; | |
71 | mp->first.used = 0; | |
71 | { mp->chunks = &mp->first; | |
72 | mp->chunk_count = 1; | |
73 | mp->first.size = FIRST_CHUNK_SIZE; | |
74 | mp->first.used = 0; | |
72 | 75 | } |
73 | 76 | |
74 | 77 | #define ROUNDUP(n,m) (((n) + (m - 1)) & ~(m-1)) |
81 | 84 | { ptr = &((char *)(mp->chunks+1))[mp->chunks->used]; |
82 | 85 | mp->chunks->used += ROUNDUP(bytes, sizeof(void*)); |
83 | 86 | } else |
84 | { size_t chunksize = (bytes < 1000 ? 4000 : bytes); | |
85 | mem_chunk *c = PL_malloc_atomic_unmanaged(chunksize+sizeof(mem_chunk)); | |
86 | ||
87 | if ( c ) | |
88 | { c->size = chunksize; | |
87 | { size_t chunksize = tmp_nalloc(4000*((size_t)1<<mp->chunk_count++)+sizeof(mem_chunk)); | |
88 | mem_chunk *c; | |
89 | ||
90 | if ( bytes > chunksize-sizeof(mem_chunk) ) | |
91 | chunksize = tmp_nalloc(bytes+sizeof(mem_chunk)); | |
92 | ||
93 | if ( (c=tmp_malloc(chunksize)) ) | |
94 | { c->size = chunksize-sizeof(mem_chunk); | |
89 | 95 | c->used = ROUNDUP(bytes, sizeof(void*)); |
90 | 96 | c->prev = mp->chunks; |
91 | 97 | mp->chunks = c; |
107 | 113 | |
108 | 114 | for(c=mp->chunks; c != &mp->first; c=p) |
109 | 115 | { p = c->prev; |
110 | PL_free(c); | |
111 | } | |
112 | mp->chunks = &mp->first; | |
116 | tmp_free(c); | |
117 | } | |
118 | mp->chunk_count = 1; | |
119 | mp->chunks = &mp->first; | |
120 | mp->first.used = 0; | |
113 | 121 | } |
114 | 122 | |
115 | 123 |
512 | 512 | PL_meta_predicate(PL_predicate("thread_create", 3, "system"), "0?+"); |
513 | 513 | PL_meta_predicate(PL_predicate("thread_signal", 2, "system"), "+0"); |
514 | 514 | #endif |
515 | PL_meta_predicate(PL_predicate("thread_idle", 2, "system"), "0+"); | |
515 | 516 | PL_meta_predicate(PL_predicate("prolog_frame_attribute", 3, "system"), "++:"); |
516 | 517 | PL_meta_predicate(PL_predicate("compile_predicates", 1, "system"), ":"); |
517 | 518 | PL_meta_predicate(PL_predicate("op", 3, "system"), "++:"); |
87 | 87 | COMMON(int) createUndefSupervisor(Definition def); |
88 | 88 | COMMON(Code) createSupervisor(Definition def); |
89 | 89 | COMMON(int) setSupervisor(Definition def); |
90 | COMMON(size_t) sizeof_supervisor(Code base); | |
90 | 91 | COMMON(size_t) supervisorLength(Code base); |
91 | 92 | COMMON(void) initSupervisors(void); |
92 | 93 | |
107 | 108 | #ifdef O_DEBUG_ATOMGC |
108 | 109 | COMMON(word) pl_track_atom(term_t which, term_t stream); |
109 | 110 | #endif |
111 | COMMON(size_t) atom_space(void); | |
110 | 112 | |
111 | 113 | /* pl-bag.c */ |
112 | 114 | COMMON(void) markAtomsFindall(PL_local_data_t *ld); |
172 | 174 | COMMON(int) checkClauseIndexSizes(Definition def, int nindexable); |
173 | 175 | COMMON(void) checkClauseIndexes(Definition def); |
174 | 176 | COMMON(void) listIndexGenerations(Definition def, gen_t gen); |
177 | COMMON(size_t) sizeofClauseIndexes(Definition def); | |
175 | 178 | |
176 | 179 | /* pl-dwim.c */ |
177 | 180 | COMMON(word) pl_dwim_match(term_t a1, term_t a2, term_t mm); |
283 | 286 | COMMON(int) checkFunctors(void); |
284 | 287 | COMMON(word) pl_current_functor(term_t name, term_t arity, |
285 | 288 | control_t h); |
289 | COMMON(size_t) functor_space(void); | |
286 | 290 | |
287 | 291 | /* pl-gc.c */ |
288 | 292 | COMMON(int) considerGarbageCollect(Stack s); |
515 | 519 | COMMON(void) ddi_add_access_gen(DirtyDefInfo ddi, gen_t access); |
516 | 520 | COMMON(int) ddi_contains_gen(DirtyDefInfo ddi, gen_t access); |
517 | 521 | COMMON(int) ddi_is_garbage(DirtyDefInfo ddi, gen_t start, Clause cl); |
522 | COMMON(size_t) sizeof_predicate(Definition def); | |
518 | 523 | |
519 | 524 | /* pl-srcfile.c */ |
520 | 525 | |
605 | 610 | COMMON(int) ensure_room_stack(Stack s, size_t n, int ex); |
606 | 611 | COMMON(int) trim_stack(Stack s); |
607 | 612 | COMMON(int) set_stack_limit(size_t limit); |
608 | COMMON(void *) stack_malloc(size_t size); | |
609 | COMMON(void *) stack_realloc(void *old, size_t size); | |
610 | COMMON(void) stack_free(void *mem); | |
611 | 613 | COMMON(const char *) signal_name(int sig); |
612 | 614 | |
613 | 615 | /* pl-sys.c */ |
2 | 2 | Author: Jan Wielemaker and Keri Harris |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1985-2017, University of Amsterdam | |
5 | Copyright (c) 1985-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | CWI, Amsterdam | |
7 | 8 | All rights reserved. |
8 | 9 | |
9 | 10 | Redistribution and use in source and binary forms, with or without |
160 | 161 | f->arity = arity; |
161 | 162 | f->flags = 0; |
162 | 163 | f->next = table[v]; |
163 | if ( !( COMPARE_AND_SWAP(&table[v], head, f) && | |
164 | if ( !( COMPARE_AND_SWAP_PTR(&table[v], head, f) && | |
164 | 165 | !GD->functors.rehashing && |
165 | 166 | table == functorDefTable->table) ) |
166 | 167 | { PL_free(f); |
522 | 523 | PL_UNLOCK(L_FUNCTOR); |
523 | 524 | return FALSE; |
524 | 525 | } |
526 | ||
527 | ||
528 | size_t | |
529 | functor_space(void) | |
530 | { size_t size = ((size_t)2<<MSB(GD->functors.highest))*sizeof(FunctorDef); | |
531 | ||
532 | size += GD->functors.highest * sizeof(struct functorDef); | |
533 | ||
534 | return size; | |
535 | } |
5132 | 5132 | if ( t ) |
5133 | 5133 | { void *nw; |
5134 | 5134 | |
5135 | tsize = stack_nrealloc(tb, tsize); | |
5135 | 5136 | if ( (nw = stack_realloc(tb, tsize)) ) |
5136 | 5137 | { LD->shift_status.trail_shifts++; |
5137 | 5138 | tb = nw; |
5150 | 5151 | olsize = sizeStack(local); |
5151 | 5152 | assert(lb == addPointer(gb, ogsize)); |
5152 | 5153 | |
5154 | gsize = stack_nrealloc(gb, lsize + gsize)-lsize; | |
5155 | g = (ogsize != gsize); | |
5156 | ||
5153 | 5157 | if ( gsize < ogsize ) /* TBD: Only copy life-part */ |
5154 | 5158 | memmove(addPointer(gb, gsize), lb, olsize); |
5155 | 5159 | |
5161 | 5165 | |
5162 | 5166 | gb = nw; |
5163 | 5167 | lb = addPointer(gb, gsize); |
5164 | if ( gsize > ogsize ) { | |
5165 | size_t copy = olsize; | |
5166 | ||
5167 | if ( lsize < olsize ) copy = lsize; | |
5168 | if ( gsize > ogsize ) | |
5169 | { size_t copy = olsize; | |
5170 | ||
5171 | if ( lsize < olsize ) | |
5172 | copy = lsize; | |
5168 | 5173 | memmove(lb, addPointer(gb, ogsize), copy); |
5169 | 5174 | } |
5170 | 5175 | } else /* realloc failed; restore */ |
204 | 204 | { size_t highest; /* Highest atom index */ |
205 | 205 | atom_array array; |
206 | 206 | AtomTable table; /* hash-table */ |
207 | Atom builtin_array; /* Builtin atoms */ | |
208 | 207 | int lookups; /* # atom lookups */ |
209 | 208 | int cmps; /* # string compares for lookup */ |
210 | 209 | int initialised; /* atoms have been initialised */ |
386 | 385 | PL_thread_info_t *free; /* Free threads */ |
387 | 386 | int highest_allocated; /* Highest with info struct */ |
388 | 387 | int thread_max; /* Size of threads array */ |
388 | int highest_id; /* Highest Id of life thread */ | |
389 | int peak_id; /* Highest Id of any thread */ | |
389 | 390 | PL_thread_info_t **threads; /* Pointers to thread-info */ |
390 | 391 | struct |
391 | 392 | { pthread_mutex_t mutex; |
1025 | 1025 | #define setGenerationFrameVal(f, gen) \ |
1026 | 1026 | do { (f)->generation = (gen); } while(0) |
1027 | 1027 | #endif |
1028 | #ifdef HAVE___SYNC_ADD_AND_FETCH_8 | |
1028 | #if defined(HAVE_GCC_ATOMIC_8) || SIZEOF_VOIDP == 8 | |
1029 | 1029 | typedef uint64_t ggen_t; |
1030 | 1030 | #else |
1031 | 1031 | #define ATOMIC_GENERATION_HACK 1 |
1033 | 1033 | { uint32_t gen_l; |
1034 | 1034 | uint32_t gen_u; |
1035 | 1035 | } ggen_t; |
1036 | #endif /*HAVE___SYNC_ADD_AND_FETCH_8*/ | |
1036 | #endif /*HAVE_GCC_ATOMIC_8 || SIZEOF_VOIDP == 8*/ | |
1037 | 1037 | #else /*O_LOGICAL_UPDATE*/ |
1038 | 1038 | #define global_generation() (0) |
1039 | 1039 | #define next_global_generation() (0) |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1985-2018, University of Amsterdam | |
5 | Copyright (c) 1985-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
2520 | 2520 | if ( !clist->args ) |
2521 | 2521 | { arg_info *ai = allocHeapOrHalt(ac*sizeof(*ai)); |
2522 | 2522 | memset(ai, 0, ac*sizeof(*ai)); |
2523 | if ( !COMPARE_AND_SWAP(&clist->args, NULL, ai) ) | |
2523 | if ( !COMPARE_AND_SWAP_PTR(&clist->args, NULL, ai) ) | |
2524 | 2524 | freeHeap(ai, ac*sizeof(*ai)); |
2525 | 2525 | } |
2526 | 2526 | |
2690 | 2690 | } |
2691 | 2691 | |
2692 | 2692 | |
2693 | size_t | |
2694 | sizeofClauseIndexes(Definition def) | |
2695 | { GET_LD | |
2696 | ClauseIndex *cip; | |
2697 | size_t size = 0; | |
2698 | ||
2699 | acquire_def(def); | |
2700 | if ( (cip=def->impl.clauses.clause_indexes) ) | |
2701 | { for(; *cip; cip++) | |
2702 | { ClauseIndex ci = *cip; | |
2703 | ||
2704 | if ( ISDEADCI(ci) ) | |
2705 | continue; | |
2706 | size += sizeofClauseIndex(ci); | |
2707 | } | |
2708 | } | |
2709 | ||
2710 | return size; | |
2711 | } | |
2712 | ||
2713 | ||
2693 | 2714 | static int |
2694 | 2715 | unify_clause_index(term_t t, ClauseIndex ci) |
2695 | 2716 | { GET_LD |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2016, VU University Amsterdam | |
5 | Copyright (c) 2016-2020, VU University Amsterdam | |
6 | CWI, Amsterdam | |
6 | 7 | All rights reserved. |
7 | 8 | |
8 | 9 | Redistribution and use in source and binary forms, with or without |
193 | 194 | { indirect *h = reserve_indirect(tab, val PASS_LD); |
194 | 195 | |
195 | 196 | h->next = buckets->buckets[ki]; |
196 | if ( !COMPARE_AND_SWAP(&buckets->buckets[ki], head, h) || | |
197 | if ( !COMPARE_AND_SWAP_PTR(&buckets->buckets[ki], head, h) || | |
197 | 198 | buckets != tab->table ) |
198 | 199 | { PL_free(h->data); |
199 | 200 | h->references = 0; |
216 | 217 | static int |
217 | 218 | bump_ref(indirect *h, unsigned int refs) |
218 | 219 | { for(;;) |
219 | { if ( COMPARE_AND_SWAP(&h->references, refs, refs+1) ) | |
220 | { if ( COMPARE_AND_SWAP_UINT(&h->references, refs, refs+1) ) | |
220 | 221 | { return TRUE; |
221 | 222 | } else |
222 | 223 | { refs = h->references; |
264 | 265 | unsigned int refs = a->references; |
265 | 266 | |
266 | 267 | if ( INDIRECT_IS_FREE(refs) && |
267 | COMPARE_AND_SWAP(&a->references, refs, INDIRECT_RESERVED_REFERENCE) ) | |
268 | COMPARE_AND_SWAP_UINT(&a->references, refs, INDIRECT_RESERVED_REFERENCE) ) | |
268 | 269 | { tab->no_hole_before = index+1; |
269 | 270 | return create_indirect(a, index, val PASS_LD); |
270 | 271 | } |
287 | 288 | refs = a->references; |
288 | 289 | |
289 | 290 | if ( INDIRECT_IS_FREE(refs) && |
290 | COMPARE_AND_SWAP(&a->references, refs, INDIRECT_RESERVED_REFERENCE) ) | |
291 | COMPARE_AND_SWAP_UINT(&a->references, refs, INDIRECT_RESERVED_REFERENCE) ) | |
291 | 292 | { ATOMIC_INC(&tab->highest); |
292 | 293 | return create_indirect(a, index, val PASS_LD); |
293 | 294 | } |
109 | 109 | #define MSB64(i) ((int)sizeof(long long)*8-1-__builtin_clzll(i)) |
110 | 110 | #endif |
111 | 111 | |
112 | #ifdef HAVE__SYNC_SYNCHRONIZE | |
113 | #define MEMORY_BARRIER() __sync_synchronize() | |
112 | #ifdef HAVE_GCC_ATOMIC | |
113 | #define MEMORY_BARRIER() __atomic_thread_fence(__ATOMIC_SEQ_CST) | |
114 | 114 | #endif |
115 | 115 | |
116 | 116 | #ifdef O_PLMT |
117 | #define ATOMIC_ADD(ptr, v) __sync_add_and_fetch(ptr, v) | |
118 | #define ATOMIC_SUB(ptr, v) __sync_sub_and_fetch(ptr, v) | |
119 | #define ATOMIC_INC(ptr) ATOMIC_ADD(ptr, 1) /* ++(*ptr) */ | |
120 | #define ATOMIC_DEC(ptr) ATOMIC_SUB(ptr, 1) /* --(*ptr) */ | |
121 | #define ATOMIC_OR(ptr, v) __sync_fetch_and_or(ptr, v) | |
122 | #define ATOMIC_AND(ptr, v) __sync_fetch_and_and(ptr, v) | |
123 | #define COMPARE_AND_SWAP(ptr,o,n) __sync_bool_compare_and_swap(ptr,o,n) | |
117 | #define ATOMIC_ADD(ptr, v) __atomic_add_fetch(ptr, v, __ATOMIC_SEQ_CST) | |
118 | #define ATOMIC_SUB(ptr, v) __atomic_sub_fetch(ptr, v, __ATOMIC_SEQ_CST) | |
119 | #define ATOMIC_INC(ptr) ATOMIC_ADD(ptr, 1) /* ++(*ptr) */ | |
120 | #define ATOMIC_DEC(ptr) ATOMIC_SUB(ptr, 1) /* --(*ptr) */ | |
121 | #define ATOMIC_OR(ptr, v) __atomic_fetch_or(ptr, v, __ATOMIC_SEQ_CST) | |
122 | #define ATOMIC_AND(ptr, v) __atomic_fetch_and(ptr, v, __ATOMIC_SEQ_CST) | |
123 | ||
124 | #define __COMPARE_AND_SWAP(at, from, to) \ | |
125 | __atomic_compare_exchange_n(at, &(from), to, FALSE, \ | |
126 | __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) | |
127 | ||
128 | static inline int | |
129 | COMPARE_AND_SWAP_PTR(void *at, void *from, void *to) | |
130 | { void **ptr = at; | |
131 | ||
132 | return __COMPARE_AND_SWAP(ptr, from, to); | |
133 | } | |
134 | ||
135 | static inline int | |
136 | COMPARE_AND_SWAP_INT64(int64_t *at, int64_t from, int64_t to) | |
137 | { return __COMPARE_AND_SWAP(at, from, to); | |
138 | } | |
139 | ||
140 | static inline int | |
141 | COMPARE_AND_SWAP_UINT64(uint64_t *at, uint64_t from, uint64_t to) | |
142 | { return __COMPARE_AND_SWAP(at, from, to); | |
143 | } | |
144 | ||
145 | static inline int | |
146 | COMPARE_AND_SWAP_INT(int *at, int from, int to) | |
147 | { return __COMPARE_AND_SWAP(at, from, to); | |
148 | } | |
149 | ||
150 | static inline int | |
151 | COMPARE_AND_SWAP_UINT(unsigned int *at, unsigned int from, unsigned int to) | |
152 | { return __COMPARE_AND_SWAP(at, from, to); | |
153 | } | |
154 | ||
155 | static inline int | |
156 | COMPARE_AND_SWAP_SIZE(size_t *at, size_t from, size_t to) | |
157 | { return __COMPARE_AND_SWAP(at, from, to); | |
158 | } | |
159 | ||
160 | static inline int | |
161 | COMPARE_AND_SWAP_WORD(word *at, word from, word to) | |
162 | { return __COMPARE_AND_SWAP(at, from, to); | |
163 | } | |
164 | ||
124 | 165 | #else |
125 | 166 | #define ATOMIC_ADD(ptr, v) (*ptr += v) |
126 | 167 | #define ATOMIC_SUB(ptr, v) (*ptr -= v) |
129 | 170 | #define ATOMIC_OR(ptr, v) (*ptr |= v) |
130 | 171 | #define ATOMIC_AND(ptr, v) (*ptr &= v) |
131 | 172 | #define COMPARE_AND_SWAP(ptr,o,n) (*ptr == o ? (*ptr = n), 1 : 0) |
173 | #define COMPARE_AND_SWAP_PTR(ptr,o,n) COMPARE_AND_SWAP(ptr,o,n) | |
174 | #define COMPARE_AND_SWAP_INT64(ptr,o,n) COMPARE_AND_SWAP(ptr,o,n) | |
175 | #define COMPARE_AND_SWAP_UINT64(ptr,o,n) COMPARE_AND_SWAP(ptr,o,n) | |
176 | #define COMPARE_AND_SWAP_INT(ptr,o,n) COMPARE_AND_SWAP(ptr,o,n) | |
177 | #define COMPARE_AND_SWAP_UINT(ptr,o,n) COMPARE_AND_SWAP(ptr,o,n) | |
178 | #define COMPARE_AND_SWAP_SIZE(ptr,o,n) COMPARE_AND_SWAP(ptr,o,n) | |
179 | #define COMPARE_AND_SWAP_WORD(ptr,o,n) COMPARE_AND_SWAP(ptr,o,n) | |
132 | 180 | #endif |
133 | 181 | |
134 | 182 | #ifndef HAVE_MSB |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1985-2018, University of Amsterdam | |
5 | Copyright (c) 1985-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
74 | 74 | #ifdef HAVE_DLOPEN /* sysvr4, elf binaries */ |
75 | 75 | |
76 | 76 | #ifdef HAVE_DLFCN_H |
77 | #define _GNU_SOURCE /* get RTLD_DEFAULT */ | |
77 | 78 | #include <dlfcn.h> |
78 | 79 | #endif |
79 | 80 | |
149 | 150 | |
150 | 151 | void * |
151 | 152 | PL_dlsym(void *handle, char *symbol) |
152 | { return dlsym(handle, symbol); | |
153 | { | |
154 | #ifdef RTLD_DEFAULT | |
155 | if ( !handle ) | |
156 | handle = RTLD_DEFAULT; | |
157 | #endif | |
158 | return dlsym(handle, symbol); | |
153 | 159 | } |
154 | 160 | |
155 | 161 | int |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1985-2012, University of Amsterdam | |
5 | Copyright (c) 1985-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | CWI, Amsterdam | |
7 | 8 | All rights reserved. |
8 | 9 | |
9 | 10 | Redistribution and use in source and binary forms, with or without |
91 | 92 | } |
92 | 93 | #endif |
93 | 94 | |
95 | /******************************* | |
96 | * TCMALLOC * | |
97 | *******************************/ | |
98 | ||
99 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
100 | If we link the main program against an alternative malloc() | |
101 | implementation we better ensure the main program depends on malloc(), | |
102 | otherwise the linker may still decide to put the alternative malloc | |
103 | library further down in the link dependencies. We should also ensure | |
104 | this dependency is not optimized away. | |
105 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
106 | ||
107 | void *_PL_tc_malloc_base; | |
108 | ||
109 | static void | |
110 | force_malloc_dependency(void) | |
111 | { _PL_tc_malloc_base = malloc(1); | |
112 | } | |
94 | 113 | |
95 | 114 | /******************************* |
96 | 115 | * MAIN * |
97 | 116 | *******************************/ |
98 | ||
99 | 117 | |
100 | 118 | int |
101 | 119 | main(int argc, char **argv) |
108 | 126 | #if O_ANSI_COLORS |
109 | 127 | PL_w32_wrap_ansi_console(); /* decode ANSI color sequences (ESC[...m) */ |
110 | 128 | #endif |
129 | ||
130 | force_malloc_dependency(); | |
111 | 131 | |
112 | 132 | if ( !PL_initialise(argc, argv) ) |
113 | 133 | PL_halt(1); |
1281 | 1281 | term_t list = PL_copy_term_ref(public); |
1282 | 1282 | int rval = TRUE; |
1283 | 1283 | |
1284 | LOCKMODULE(module); | |
1285 | 1284 | for_table(module->public, name, value, |
1286 | 1285 | { if ( !PL_unify_list(list, head, list) || |
1287 | 1286 | !unify_functor(head, (functor_t)name, GP_NAMEARITY) ) |
1289 | 1288 | break; |
1290 | 1289 | } |
1291 | 1290 | }) |
1292 | UNLOCKMODULE(module); | |
1293 | 1291 | if ( rval ) |
1294 | 1292 | return PL_unify_nil(list); |
1295 | 1293 | |
1296 | 1294 | fail; |
1297 | 1295 | } |
1296 | ||
1297 | ||
1298 | static size_t | |
1299 | sizeof_module(Module m) | |
1300 | { GET_LD | |
1301 | size_t size = sizeof(*m); | |
1302 | ||
1303 | if ( m->public) size += sizeofTable(m->public); | |
1304 | if ( m->procedures) size += sizeofTable(m->procedures); | |
1305 | if ( m->operators) size += sizeofTable(m->operators); | |
1306 | ||
1307 | for_table(m->procedures, name, value, | |
1308 | { Procedure proc = value; | |
1309 | Definition def = proc->definition; | |
1310 | ||
1311 | size += sizeof(*proc); | |
1312 | ||
1313 | if ( def->module == m && false(def, P_FOREIGN) ) | |
1314 | { Definition def = getProcDefinition(proc); | |
1315 | size += sizeof_predicate(def); | |
1316 | } | |
1317 | }); | |
1318 | ||
1319 | return size; | |
1320 | } | |
1321 | ||
1298 | 1322 | |
1299 | 1323 | |
1300 | 1324 | static |
1329 | 1353 | { return unify_export_list(a, m PASS_LD); |
1330 | 1354 | } else if ( pname == ATOM_class ) |
1331 | 1355 | { return PL_unify_atom(a, m->class); |
1356 | } else if ( pname == ATOM_size ) | |
1357 | { return PL_unify_int64(a, sizeof_module(m)); | |
1332 | 1358 | } else if ( pname == ATOM_program_size ) |
1333 | 1359 | { return PL_unify_int64(a, m->code_size); |
1334 | 1360 | } else if ( pname == ATOM_last_modified_generation ) |
1486 | 1512 | if ( proc->definition == old ) |
1487 | 1513 | { DEBUG(1, Sdprintf("Patched def of %s\n", |
1488 | 1514 | procedureName(proc))); |
1515 | shareDefinition(new); | |
1489 | 1516 | proc->definition = new; |
1517 | if ( unshareDefinition(old) == 0 ) | |
1518 | lingerDefinition(old); | |
1490 | 1519 | } |
1491 | 1520 | }); |
1492 | 1521 | |
1610 | 1639 | |
1611 | 1640 | nproc->flags = pflags; |
1612 | 1641 | nproc->source_no = 0; |
1642 | shareDefinition(proc->definition); | |
1613 | 1643 | nproc->definition = proc->definition; |
1614 | shareDefinition(proc->definition); | |
1615 | 1644 | |
1616 | 1645 | LOCKMODULE(destination); |
1617 | 1646 | old = addHTable(destination->procedures, |
5213 | 5213 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
5214 | 5214 | |
5215 | 5215 | static size_t |
5216 | heapUsed(void) | |
5217 | { | |
5218 | #ifdef HAVE_BOEHM_GC | |
5219 | return GC_get_heap_size(); | |
5220 | #else | |
5216 | programSpace(void) | |
5217 | { size_t allocated = heapUsed(); | |
5218 | ||
5219 | if ( allocated ) | |
5220 | return allocated - GD->statistics.stack_space; | |
5221 | ||
5221 | 5222 | return 0; |
5222 | #endif | |
5223 | } | |
5223 | } | |
5224 | ||
5224 | 5225 | |
5225 | 5226 | static size_t |
5226 | 5227 | CStackSize(PL_local_data_t *ld) |
5302 | 5303 | v[1] = roomStack(trail); |
5303 | 5304 | vn = 2; |
5304 | 5305 | } else if ( key == ATOM_program ) |
5305 | { v[0] = heapUsed(); | |
5306 | { v[0] = programSpace(); | |
5306 | 5307 | v[1] = 0; |
5307 | 5308 | vn = 2; |
5308 | 5309 | } else if ( key == ATOM_garbage_collection ) |
5390 | 5391 | v->value.i = CStackSize(LD); |
5391 | 5392 | else if (key == ATOM_atoms) /* atoms */ |
5392 | 5393 | v->value.i = GD->statistics.atoms; |
5394 | else if (key == ATOM_atom_space) /* atom_space */ | |
5395 | v->value.i = atom_space(); | |
5393 | 5396 | else if (key == ATOM_functors) /* functors */ |
5394 | 5397 | v->value.i = GD->statistics.functors; |
5398 | else if (key == ATOM_functor_space) /* functor_space */ | |
5399 | v->value.i = functor_space(); | |
5395 | 5400 | else if (key == ATOM_predicates) /* predicates */ |
5396 | 5401 | v->value.i = GD->statistics.predicates; |
5397 | 5402 | else if (key == ATOM_clauses) /* clauses */ |
5419 | 5424 | v->value.i = GC_get_gc_no(); |
5420 | 5425 | #endif |
5421 | 5426 | else if (key == ATOM_heapused) /* heap usage */ |
5422 | v->value.i = heapUsed(); | |
5427 | v->value.i = programSpace(); | |
5423 | 5428 | #ifdef O_ATOMGC |
5424 | 5429 | else if (key == ATOM_agc) |
5425 | 5430 | v->value.i = GD->atoms.gc; |
5467 | 5472 | else if ( key == ATOM_thread_cputime ) |
5468 | 5473 | { v->type = V_FLOAT; |
5469 | 5474 | v->value.f = GD->statistics.thread_cputime; |
5470 | } | |
5475 | } else if ( key == ATOM_threads_peak ) | |
5476 | v->value.i = GD->thread.peak_id; | |
5471 | 5477 | #endif |
5472 | 5478 | else if (key == ATOM_table_space_used) |
5473 | 5479 | { alloc_pool *pool; |
140 | 140 | do |
141 | 141 | { o = m->lingering; |
142 | 142 | c->next = o; |
143 | } while( !COMPARE_AND_SWAP(&m->lingering, o, c) ); | |
143 | } while( !COMPARE_AND_SWAP_PTR(&m->lingering, o, c) ); | |
144 | 144 | |
145 | 145 | DEBUG(MSG_PROC_COUNT, Sdprintf("Linger %s\n", predicateName(def))); |
146 | 146 | ATOMIC_SUB(&m->code_size, sizeof(*def)); |
247 | 247 | } |
248 | 248 | } else |
249 | 249 | { proc = (Procedure) allocHeapOrHalt(sizeof(struct procedure)); |
250 | shareDefinition(def); | |
250 | 251 | proc->definition = def; |
251 | 252 | proc->flags = flags; |
252 | 253 | proc->source_no = 0; |
253 | 254 | addNewHTable(m->procedures, (void *)functor, proc); |
254 | shareDefinition(def); | |
255 | 255 | } |
256 | 256 | UNLOCKMODULE(m); |
257 | 257 | |
1135 | 1135 | do |
1136 | 1136 | { o = GD->clauses.lingering; |
1137 | 1137 | cref->d.gnext = o; |
1138 | } while(!COMPARE_AND_SWAP(&GD->clauses.lingering, o, cref) ); | |
1138 | } while(!COMPARE_AND_SWAP_PTR(&GD->clauses.lingering, o, cref) ); | |
1139 | 1139 | |
1140 | 1140 | ATOMIC_INC(&GD->clauses.lingering_count); |
1141 | 1141 | } |
1148 | 1148 | { ClauseRef cref; |
1149 | 1149 | |
1150 | 1150 | if ( !(cref = GD->clauses.lingering) || |
1151 | !COMPARE_AND_SWAP(&GD->clauses.lingering, cref, NULL) ) | |
1151 | !COMPARE_AND_SWAP_PTR(&GD->clauses.lingering, cref, NULL) ) | |
1152 | 1152 | return; /* no work or someone else doing it */ |
1153 | 1153 | GD->clauses.lingering_count = 0; |
1154 | 1154 | |
1195 | 1195 | static void |
1196 | 1196 | setLastModifiedPredicate(Definition def, gen_t gen) |
1197 | 1197 | { Module m = def->module; |
1198 | gen_t lmm; | |
1198 | 1199 | |
1199 | 1200 | def->last_modified = gen; |
1200 | ||
1201 | #ifdef HAVE___SYNC_ADD_AND_FETCH_8 | |
1202 | { gen_t lmm; | |
1203 | 1201 | |
1204 | 1202 | do |
1205 | 1203 | { lmm = m->last_modified; |
1206 | 1204 | } while ( lmm < gen && |
1207 | !COMPARE_AND_SWAP(&m->last_modified, lmm, gen) ); | |
1208 | } | |
1209 | #else | |
1210 | LOCKMODULE(m); | |
1211 | if ( m->last_modified < gen ) | |
1212 | m->last_modified = gen; | |
1213 | UNLOCKMODULE(m); | |
1214 | #endif | |
1205 | !COMPARE_AND_SWAP_UINT64(&m->last_modified, lmm, gen) ); | |
1215 | 1206 | } |
1216 | 1207 | |
1217 | 1208 | |
2393 | 2384 | int rc = TRUE; |
2394 | 2385 | |
2395 | 2386 | if ( GD->procedures.dirty->size > 0 && |
2396 | COMPARE_AND_SWAP(&GD->clauses.cgc_active, FALSE, TRUE) ) | |
2387 | COMPARE_AND_SWAP_INT(&GD->clauses.cgc_active, FALSE, TRUE) ) | |
2397 | 2388 | { size_t removed = 0; |
2398 | 2389 | size_t erased_pending = GD->clauses.erased_size; |
2399 | 2390 | double gct, t0 = ThreadCPUTime(LD, CPU_USER); |
2605 | 2596 | /* done the job for us. */ |
2606 | 2597 | LOCKMODULE(m); |
2607 | 2598 | if ( (odef=proc->definition) != def ) /* Nope, we must link the def */ |
2608 | { proc->definition = def; | |
2609 | shareDefinition(def); | |
2599 | { shareDefinition(def); | |
2600 | proc->definition = def; | |
2610 | 2601 | |
2611 | 2602 | if ( unshareDefinition(odef) == 0 ) |
2612 | 2603 | { |
3200 | 3191 | |
3201 | 3192 | static size_t |
3202 | 3193 | num_visible_clauses(Definition def, atom_t key) |
3203 | { GET_LD; | |
3194 | { GET_LD | |
3204 | 3195 | |
3205 | 3196 | if ( LD->gen_reload != GEN_INVALID ) |
3206 | 3197 | { ClauseRef c; |
3222 | 3213 | return def->impl.clauses.number_of_clauses; |
3223 | 3214 | else |
3224 | 3215 | return def->impl.clauses.number_of_rules; |
3216 | } | |
3217 | ||
3218 | ||
3219 | size_t | |
3220 | sizeof_predicate(Definition def) | |
3221 | { GET_LD | |
3222 | size_t size = sizeof(*def); | |
3223 | ||
3224 | size += sizeof_supervisor(def->codes); | |
3225 | ||
3226 | if ( false(def, P_FOREIGN) ) | |
3227 | { ClauseRef c; | |
3228 | ||
3229 | acquire_def(def); | |
3230 | for(c = def->impl.clauses.first_clause; c; c = c->next) | |
3231 | { Clause cl = c->value.clause; | |
3232 | ||
3233 | size += sizeofClause(cl->code_size); | |
3234 | size += SIZEOF_CREF_CLAUSE; | |
3235 | } | |
3236 | release_def(def); | |
3237 | ||
3238 | size += sizeofClauseIndexes(def); | |
3239 | } | |
3240 | ||
3241 | return size; | |
3225 | 3242 | } |
3226 | 3243 | |
3227 | 3244 | |
3320 | 3337 | if ( def->impl.clauses.number_of_clauses == 0 && false(def, P_DYNAMIC) ) |
3321 | 3338 | fail; |
3322 | 3339 | return PL_unify_integer(value, num_visible_clauses(def, key)); |
3340 | } else if ( key == ATOM_size ) | |
3341 | { def = getProcDefinition(proc); | |
3342 | return PL_unify_integer(value, sizeof_predicate(def)); | |
3323 | 3343 | } else if ( tbl_is_predicate_attribute(key) ) |
3324 | 3344 | { size_t sz_value; |
3325 | 3345 |
2497 | 2497 | |
2498 | 2498 | static cucharp |
2499 | 2499 | float_tag(cucharp in, cucharp tag) |
2500 | { while(*in == *tag) | |
2500 | { while(*in && *in == *tag) | |
2501 | 2501 | in++, tag++; |
2502 | 2502 | |
2503 | 2503 | if ( !*tag ) |
2504 | 2504 | { int c; |
2505 | 2505 | |
2506 | utf8_get_uchar(in, &c); | |
2507 | if ( !PlIdContW(c) ) | |
2508 | return in; | |
2506 | if ( *in ) | |
2507 | { utf8_get_uchar(in, &c); | |
2508 | if ( PlIdContW(c) ) | |
2509 | return NULL; | |
2510 | } | |
2511 | ||
2512 | return in; | |
2509 | 2513 | } |
2510 | 2514 | |
2511 | 2515 | return NULL; |
2526 | 2530 | |
2527 | 2531 | if ( (s=float_tag(*in, (cucharp)"Inf")) ) |
2528 | 2532 | { if ( *start == '-' ) |
2529 | value->value.f = strtod("-Inf", NULL); | |
2533 | value->value.f = -HUGE_VAL; | |
2530 | 2534 | else |
2531 | value->value.f = strtod("Inf", NULL); | |
2535 | value->value.f = HUGE_VAL; | |
2532 | 2536 | } else if ( (s=float_tag(*in, (cucharp)"NaN")) && |
2533 | 2537 | starts_1dot(start) ) |
2534 | 2538 | { char *e; |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2007-2013, University of Amsterdam | |
5 | Copyright (c) 2007-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | CWI, Amsterdam | |
7 | 8 | All rights reserved. |
8 | 9 | |
9 | 10 | Redistribution and use in source and binary forms, with or without |
60 | 61 | |
61 | 62 | return TRUE; |
62 | 63 | } else |
63 | { segchunk *chunk = PL_malloc(SEGSTACK_CHUNKSIZE); | |
64 | { size_t chunksize = tmp_nalloc((size_t)1024<<stack->chunk_count++); | |
65 | segchunk *chunk = tmp_malloc(chunksize); | |
64 | 66 | |
65 | 67 | if ( !chunk ) |
66 | 68 | return FALSE; /* out of memory */ |
67 | 69 | |
68 | 70 | chunk->allocated = TRUE; |
69 | chunk->size = SEGSTACK_CHUNKSIZE; | |
71 | chunk->size = chunksize; | |
70 | 72 | chunk->next = NULL; |
71 | 73 | chunk->previous = stack->last; |
72 | 74 | chunk->top = CHUNK_DATA(chunk); /* async scanning */ |
127 | 129 | { stack->last = chunk->previous; |
128 | 130 | stack->last->next = NULL; |
129 | 131 | if ( chunk->allocated ) |
130 | PL_free(chunk); | |
132 | tmp_free(chunk); | |
131 | 133 | |
132 | 134 | chunk = stack->last; |
133 | 135 | stack->base = CHUNK_DATA(chunk); |
134 | 136 | stack->max = addPointer(chunk, chunk->size); |
135 | 137 | stack->top = chunk->top; |
138 | stack->chunk_count--; | |
136 | 139 | goto again; |
137 | 140 | } |
138 | 141 | } |
170 | 173 | { if ( chunk->previous ) |
171 | 174 | { segchunk *del = chunk; |
172 | 175 | |
176 | stack->chunk_count--; | |
173 | 177 | stack->last = chunk->previous; |
174 | 178 | stack->last->next = NULL; |
175 | 179 | chunk = stack->last; |
179 | 183 | stack->max = addPointer(chunk, chunk->size); |
180 | 184 | |
181 | 185 | if ( del->allocated ) |
182 | PL_free(del); | |
186 | tmp_free(del); | |
183 | 187 | |
184 | 188 | goto again; |
185 | 189 | } |
244 | 248 | { segchunk *c = s->first; |
245 | 249 | segchunk *n; |
246 | 250 | |
247 | if ( !c->allocated ) /* statically allocated first chunk */ | |
251 | if ( !c->allocated ) /* statically allocated first chunk */ | |
248 | 252 | { n = c->next; |
249 | 253 | |
250 | 254 | c->next = NULL; |
251 | 255 | s->last = c; |
252 | 256 | s->base = s->top = c->top; |
253 | 257 | s->max = addPointer(c, c->size); |
258 | s->chunk_count = 1; | |
254 | 259 | |
255 | 260 | for(c=n; c; c = n) |
256 | 261 | { n = c->next; |
257 | PL_free(c); | |
262 | tmp_free(c); | |
258 | 263 | } |
259 | 264 | } else /* all dynamic chunks */ |
260 | 265 | { for(; c; c = n) |
261 | 266 | { n = c->next; |
262 | PL_free(c); | |
267 | tmp_free(c); | |
263 | 268 | } |
264 | 269 | memset(s, 0, sizeof(*s)); |
265 | 270 | } |
35 | 35 | #ifndef PL_SEGSTACK_H_INCLUDED |
36 | 36 | #define PL_SEGSTACK_H_INCLUDED |
37 | 37 | |
38 | #define SEGSTACK_CHUNKSIZE (1*1024) | |
39 | ||
40 | 38 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
41 | 39 | The segchunk struct has its data attached to its back. The data field |
42 | 40 | itself is typed double to ensure that the data is properly aligned to |
59 | 57 | typedef struct |
60 | 58 | { size_t unit_size; |
61 | 59 | /* below clean using memset() */ |
60 | int chunk_count; | |
62 | 61 | segchunk *first; |
63 | 62 | segchunk *last; |
64 | 63 | char *base; |
169 | 168 | assert(len > sizeof(*chunk)); |
170 | 169 | assert(unit_size%sizeof(void*) == 0); |
171 | 170 | #endif |
172 | chunk->size = len; | |
173 | stack->base = stack->top = chunk->top = CHUNK_DATA(chunk); | |
174 | stack->last = stack->first = chunk; | |
175 | stack->max = addPointer(chunk, len); | |
176 | chunk->allocated = 0; | |
177 | chunk->next = NULL; | |
178 | chunk->previous = NULL; | |
171 | chunk->size = len; | |
172 | stack->base = stack->top = chunk->top = CHUNK_DATA(chunk); | |
173 | stack->last = stack->first = chunk; | |
174 | stack->max = addPointer(chunk, len); | |
175 | stack->chunk_count = 1; | |
176 | chunk->allocated = 0; | |
177 | chunk->next = NULL; | |
178 | chunk->previous = NULL; | |
179 | 179 | } else |
180 | 180 | { memset(&stack->first, 0, sizeof(*stack)-offsetof(segstack,first)); |
181 | 181 | } |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1985-2019, University of Amsterdam | |
5 | Copyright (c) 1985-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | CWI, Amsterdam |
8 | 8 | All rights reserved. |
123 | 123 | initFlags(); |
124 | 124 | DEBUG(1, Sdprintf("Foreign Predicates ...\n")); |
125 | 125 | initBuildIns(); |
126 | DEBUG(1, Sdprintf("TCMalloc binding ...\n")); | |
127 | initTCMalloc(); | |
126 | 128 | DEBUG(1, Sdprintf("Operators ...\n")); |
127 | 129 | initOperators(); |
128 | 130 | DEBUG(1, Sdprintf("GMP ...\n")); |
1433 | 1435 | size_t iglobal = nextStackSizeAbove(minglobal-1); |
1434 | 1436 | size_t ilocal = nextStackSizeAbove(minlocal-1); |
1435 | 1437 | |
1438 | itrail = stack_nalloc(itrail); | |
1439 | minarg = stack_nalloc(minarg); | |
1440 | iglobal = stack_nalloc(iglobal+ilocal)-ilocal; | |
1441 | ||
1436 | 1442 | gBase = NULL; |
1437 | 1443 | tBase = NULL; |
1438 | 1444 | aBase = NULL; |
1448 | 1454 | return FALSE; |
1449 | 1455 | } |
1450 | 1456 | |
1451 | lBase = (LocalFrame) addPointer(gBase, iglobal); | |
1457 | lBase = (LocalFrame) addPointer(gBase, iglobal); | |
1452 | 1458 | |
1453 | 1459 | init_stack((Stack)&LD->stacks.global, |
1454 | 1460 | "global", iglobal, 512*SIZEOF_VOIDP, TRUE); |
1483 | 1489 | aTop = NULL; |
1484 | 1490 | aBase = NULL; |
1485 | 1491 | } |
1486 | } | |
1487 | ||
1488 | ||
1489 | void * | |
1490 | stack_malloc(size_t size) | |
1491 | { void *mem = malloc(size+sizeof(size_t)); | |
1492 | ||
1493 | if ( mem ) | |
1494 | { size_t *sp = mem; | |
1495 | *sp++ = size; | |
1496 | #ifdef SECURE_GC | |
1497 | memset(sp, 0xFB, size); | |
1498 | #endif | |
1499 | ATOMIC_ADD(&GD->statistics.stack_space, size); | |
1500 | ||
1501 | return sp; | |
1502 | } | |
1503 | ||
1504 | return NULL; | |
1505 | } | |
1506 | ||
1507 | void * | |
1508 | stack_realloc(void *old, size_t size) | |
1509 | { size_t *sp = old; | |
1510 | size_t osize = *--sp; | |
1511 | void *mem; | |
1512 | ||
1513 | #ifdef SECURE_GC | |
1514 | if ( (mem = stack_malloc(size)) ) | |
1515 | { memcpy(mem, old, (size>osize?osize:size)); | |
1516 | stack_free(old); | |
1517 | return mem; | |
1518 | } | |
1519 | #else | |
1520 | if ( (mem = realloc(sp, size+sizeof(size_t))) ) | |
1521 | { sp = mem; | |
1522 | *sp++ = size; | |
1523 | if ( size > osize ) | |
1524 | ATOMIC_ADD(&GD->statistics.stack_space, size-osize); | |
1525 | else | |
1526 | ATOMIC_SUB(&GD->statistics.stack_space, osize-size); | |
1527 | return sp; | |
1528 | } | |
1529 | #endif | |
1530 | ||
1531 | return NULL; | |
1532 | } | |
1533 | ||
1534 | void | |
1535 | stack_free(void *mem) | |
1536 | { size_t *sp = mem; | |
1537 | size_t osize = *--sp; | |
1538 | ||
1539 | ATOMIC_SUB(&GD->statistics.stack_space, osize); | |
1540 | ||
1541 | #ifdef SECURE_GC | |
1542 | memset(sp, 0xFB, osize+sizeof(size_t)); | |
1543 | #endif | |
1544 | free(sp); | |
1545 | 1492 | } |
1546 | 1493 | |
1547 | 1494 |
441 | 441 | } |
442 | 442 | } |
443 | 443 | |
444 | /* returns 0 for shared static supervisors | |
445 | */ | |
446 | ||
447 | size_t | |
448 | sizeof_supervisor(Code base) | |
449 | { size_t size = (size_t)base[-1]; | |
450 | ||
451 | return size*sizeof(code); | |
452 | } | |
453 | ||
444 | 454 | |
445 | 455 | /******************************* |
446 | 456 | * INIT * |
164 | 164 | #ifdef O_DEBUG |
165 | 165 | int mytid = PL_thread_self(); |
166 | 166 | assert(mytid == atrie->tid); |
167 | int rc = COMPARE_AND_SWAP(&atrie->tid, mytid, 0); | |
167 | int rc = COMPARE_AND_SWAP_INT(&atrie->tid, mytid, 0); | |
168 | 168 | assert(rc); |
169 | 169 | #else |
170 | 170 | atrie->tid = 0; |
175 | 175 | take_trie(trie *atrie, int tid) |
176 | 176 | { assert(atrie->data.worklist != WL_DYNAMIC); |
177 | 177 | #ifdef O_DEBUG |
178 | int rc = COMPARE_AND_SWAP(&atrie->tid, 0, tid); | |
178 | int rc = COMPARE_AND_SWAP_INT(&atrie->tid, 0, tid); | |
179 | 179 | assert(rc); |
180 | 180 | #else |
181 | 181 | atrie->tid = tid; |
2066 | 2066 | if ( !(pool = GD->tabling.node_pool) ) |
2067 | 2067 | { if ( (pool = new_alloc_pool("shared_table_space", |
2068 | 2068 | GD->options.sharedTableSpace)) ) |
2069 | { if ( !COMPARE_AND_SWAP(&GD->tabling.node_pool, NULL, pool) ) | |
2069 | { if ( !COMPARE_AND_SWAP_PTR(&GD->tabling.node_pool, NULL, pool) ) | |
2070 | 2070 | { free_alloc_pool(pool); |
2071 | 2071 | pool = GD->tabling.node_pool; |
2072 | 2072 | } |
2094 | 2094 | t->release_node = release_variant_table_node; |
2095 | 2095 | symb = trie_symbol(t); |
2096 | 2096 | |
2097 | if ( COMPARE_AND_SWAP(tp, NULL, t) ) | |
2097 | if ( COMPARE_AND_SWAP_PTR(tp, NULL, t) ) | |
2098 | 2098 | { if ( shared ) |
2099 | 2099 | { set(t, TRIE_ISSHARED); |
2100 | 2100 | acquire_trie(t); /* bit misuse */ |
2299 | 2299 | #ifdef O_PLMT |
2300 | 2300 | if ( shared ) |
2301 | 2301 | { set(atrie, TRIE_ISSHARED); |
2302 | if ( COMPARE_AND_SWAP(&node->value, 0, symb) ) | |
2302 | if ( COMPARE_AND_SWAP_WORD(&node->value, 0, symb) ) | |
2303 | 2303 | { set(node, TN_PRIMARY); |
2304 | 2304 | ATOMIC_INC(&variants->value_count); |
2305 | 2305 | } else |
5350 | 5350 | if ( !(t=child->affected) ) |
5351 | 5351 | { t = newHTable(4); |
5352 | 5352 | t->free_symbol = idg_free_affected; |
5353 | if ( !COMPARE_AND_SWAP(&child->affected, NULL, t) ) | |
5353 | if ( !COMPARE_AND_SWAP_PTR(&child->affected, NULL, t) ) | |
5354 | 5354 | destroyHTable(t); |
5355 | 5355 | } |
5356 | 5356 | addHTable(t, parent, child); |
5358 | 5358 | if ( !(t=parent->dependent) ) |
5359 | 5359 | { t = newHTable(4); |
5360 | 5360 | t->free_symbol = idg_free_dependent; |
5361 | if ( !COMPARE_AND_SWAP(&parent->dependent, NULL, t) ) | |
5361 | if ( !COMPARE_AND_SWAP_PTR(&parent->dependent, NULL, t) ) | |
5362 | 5362 | destroyHTable(t); |
5363 | 5363 | } |
5364 | 5364 | addHTable(t, child, parent); |
5382 | 5382 | if ( true(def, P_INCREMENTAL) ) |
5383 | 5383 | { idg_node *n = idg_new(atrie); |
5384 | 5384 | |
5385 | if ( !COMPARE_AND_SWAP(&atrie->data.IDG, NULL, n) ) | |
5385 | if ( !COMPARE_AND_SWAP_PTR(&atrie->data.IDG, NULL, n) ) | |
5386 | 5386 | idg_destroy(n); |
5387 | 5387 | } |
5388 | 5388 | } |
5521 | 5521 | assert(!atrie->data.worklist || atrie->data.worklist == WL_GROUND); |
5522 | 5522 | atrie->data.worklist = WL_DYNAMIC; |
5523 | 5523 | n = idg_new(atrie); |
5524 | if ( !COMPARE_AND_SWAP(&atrie->data.IDG, NULL, n) ) | |
5524 | if ( !COMPARE_AND_SWAP_PTR(&atrie->data.IDG, NULL, n) ) | |
5525 | 5525 | idg_destroy(n); |
5526 | 5526 | } |
5527 | 5527 | |
6253 | 6253 | { p = allocHeapOrHalt(sizeof(*p)); |
6254 | 6254 | |
6255 | 6255 | clear_table_props(p); |
6256 | if ( !COMPARE_AND_SWAP(&def->tabling, NULL, p) ) | |
6256 | if ( !COMPARE_AND_SWAP_PTR(&def->tabling, NULL, p) ) | |
6257 | 6257 | { p = def->tabling; |
6258 | 6258 | freeHeap(p, sizeof(*p)); |
6259 | 6259 | } |
6586 | 6586 | |
6587 | 6587 | if ( !(ta=GD->tabling.waiting) ) |
6588 | 6588 | { ta = new_trie_array(); |
6589 | if ( !COMPARE_AND_SWAP(&GD->tabling.waiting, NULL, ta) ) | |
6589 | if ( !COMPARE_AND_SWAP_PTR(&GD->tabling.waiting, NULL, ta) ) | |
6590 | 6590 | { freeHeap(ta, sizeof(*ta)); |
6591 | 6591 | ta = GD->tabling.waiting; |
6592 | 6592 | } |
6601 | 6601 | outOfCore(); |
6602 | 6602 | |
6603 | 6603 | memset(newblock, 0, bs*sizeof(trie*)); |
6604 | if ( !COMPARE_AND_SWAP(&ta->blocks[idx], NULL, newblock-bs) ) | |
6604 | if ( !COMPARE_AND_SWAP_PTR(&ta->blocks[idx], NULL, newblock-bs) ) | |
6605 | 6605 | PL_free(newblock); |
6606 | 6606 | } |
6607 | 6607 | } |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1999-2019, University of Amsterdam, | |
5 | Copyright (c) 1999-2020, University of Amsterdam, | |
6 | 6 | VU University Amsterdam |
7 | 7 | CWI, Amsterdam |
8 | 8 | All rights reserved. |
237 | 237 | *******************************/ |
238 | 238 | |
239 | 239 | static Table threadTable; /* name --> reference symbol */ |
240 | static int thread_highest_id; /* Highest handed thread-id */ | |
241 | 240 | static int threads_ready = FALSE; /* Prolog threads available */ |
242 | 241 | static Table queueTable; /* name --> queue */ |
243 | 242 | static simpleMutex queueTable_mutex; /* GC synchronization */ |
446 | 445 | static void destroy_message_queue(message_queue *queue); |
447 | 446 | static void destroy_thread_message_queue(message_queue *queue); |
448 | 447 | static void init_message_queue(message_queue *queue, size_t max_size); |
448 | static size_t sizeof_message_queue(message_queue *queue); | |
449 | static size_t sizeof_local_definitions(PL_local_data_t *ld); | |
449 | 450 | static void freeThreadSignals(PL_local_data_t *ld); |
450 | 451 | static thread_handle *create_thread_handle(PL_thread_info_t *info); |
451 | 452 | static void free_thread_info(PL_thread_info_t *info); |
633 | 634 | rc2 = callEventHook(PLEV_THREAD_EXIT, info); |
634 | 635 | if ( (!rc1 || !rc2) && exception_term ) |
635 | 636 | { Sdprintf("Event hook \"thread_finished\" left an exception\n"); |
636 | PL_write_term(Serror, exception_term, 1200, PL_WRT_QUOTED|PL_WRT_NEWLINE); | |
637 | PL_write_term(Serror, exception_term, 1200, | |
638 | PL_WRT_QUOTED|PL_WRT_NEWLINE); | |
637 | 639 | PL_clear_exception(); |
638 | 640 | } |
639 | 641 | info->in_exit_hooks = FALSE; |
775 | 777 | } |
776 | 778 | set_system_thread_id(info); |
777 | 779 | |
778 | for(i=2; i<=thread_highest_id; i++) | |
780 | for(i=2; i<=GD->thread.highest_id; i++) | |
779 | 781 | { if ( (info=GD->thread.threads[i]) ) |
780 | 782 | { if ( info->status != PL_THREAD_UNUSED ) |
781 | 783 | { freePrologThread(info->thread_data, TRUE); |
783 | 785 | } |
784 | 786 | } |
785 | 787 | } |
786 | thread_highest_id = 1; | |
788 | GD->thread.highest_id = 1; | |
787 | 789 | |
788 | 790 | GD->statistics.thread_cputime = 0.0; |
789 | 791 | GD->statistics.threads_created = 1; |
863 | 865 | memset(info, 0, sizeof(*info)); |
864 | 866 | info->pl_tid = 1; |
865 | 867 | info->debug = TRUE; |
866 | thread_highest_id = 1; | |
868 | GD->thread.highest_id = 1; | |
867 | 869 | info->thread_data = &PL_local_data; |
868 | 870 | info->status = PL_THREAD_RUNNING; |
869 | 871 | PL_local_data.thread.info = info; |
945 | 947 | |
946 | 948 | sem_init(sem_canceled_ptr, USYNC_THREAD, 0); |
947 | 949 | |
948 | for(i=1; i<= thread_highest_id; i++) | |
950 | for(i=1; i<= GD->thread.highest_id; i++) | |
949 | 951 | { PL_thread_info_t *info = GD->thread.threads[i]; |
950 | 952 | |
951 | 953 | if ( info && info->thread_data && i != me ) |
1016 | 1018 | term_t tail = PL_copy_term_ref(running); |
1017 | 1019 | |
1018 | 1020 | rc = TRUE; |
1019 | for(i = 1; i <= thread_highest_id; i++) | |
1021 | for(i = 1; i <= GD->thread.highest_id; i++) | |
1020 | 1022 | { PL_thread_info_t *info = GD->thread.threads[i]; |
1021 | 1023 | |
1022 | 1024 | if ( info && info->thread_data && i != me ) |
1114 | 1116 | |
1115 | 1117 | if ( tid == 0 ) |
1116 | 1118 | tid = PL_thread_self(); |
1117 | if ( tid < 1 || tid > thread_highest_id ) | |
1119 | if ( tid < 1 || tid > GD->thread.highest_id ) | |
1118 | 1120 | return FALSE; |
1119 | 1121 | |
1120 | 1122 | info = GD->thread.threads[tid]; |
1201 | 1203 | |
1202 | 1204 | do |
1203 | 1205 | { h = gced_threads; |
1204 | } while ( h && !COMPARE_AND_SWAP(&gced_threads, h, h->next_free) ); | |
1206 | } while ( h && !COMPARE_AND_SWAP_PTR(&gced_threads, h, h->next_free) ); | |
1205 | 1207 | |
1206 | 1208 | if ( h ) |
1207 | 1209 | { if ( GD->cleaning == CLN_NORMAL ) |
1244 | 1246 | do |
1245 | 1247 | { h = gced_threads; |
1246 | 1248 | ref->next_free = h; |
1247 | } while( !COMPARE_AND_SWAP(&gced_threads, h, ref) ); | |
1249 | } while( !COMPARE_AND_SWAP_PTR(&gced_threads, h, ref) ); | |
1248 | 1250 | |
1249 | 1251 | start_thread_gc_thread(); |
1250 | 1252 | } |
1357 | 1359 | |
1358 | 1360 | do |
1359 | 1361 | { info = GD->thread.free; |
1360 | } while ( info && !COMPARE_AND_SWAP(&GD->thread.free, info, info->next_free) ); | |
1362 | } while ( info && !COMPARE_AND_SWAP_PTR(&GD->thread.free, info, info->next_free) ); | |
1361 | 1363 | |
1362 | 1364 | if ( info ) |
1363 | 1365 | { int i = info->pl_tid; |
1374 | 1376 | i = info->pl_tid = ++GD->thread.highest_allocated; |
1375 | 1377 | if ( i == GD->thread.thread_max ) |
1376 | 1378 | resizeThreadMax(); |
1379 | if ( i > GD->thread.peak_id ) | |
1380 | GD->thread.peak_id = i; | |
1377 | 1381 | |
1378 | 1382 | assert(GD->thread.threads[i] == NULL); |
1379 | 1383 | GD->thread.threads[i] = info; |
1390 | 1394 | info->debug = TRUE; |
1391 | 1395 | |
1392 | 1396 | do |
1393 | { mx = thread_highest_id; | |
1397 | { mx = GD->thread.highest_id; | |
1394 | 1398 | } while ( info->pl_tid > mx && |
1395 | !COMPARE_AND_SWAP(&thread_highest_id, mx, info->pl_tid) ); | |
1399 | !COMPARE_AND_SWAP_INT(&GD->thread.highest_id, mx, info->pl_tid) ); | |
1396 | 1400 | |
1397 | 1401 | ATOMIC_INC(&GD->statistics.threads_created); |
1398 | 1402 | |
1416 | 1420 | int |
1417 | 1421 | PL_unify_thread_id(term_t t, int i) |
1418 | 1422 | { if ( i < 1 || |
1419 | i > thread_highest_id || | |
1423 | i > GD->thread.highest_id || | |
1420 | 1424 | GD->thread.threads[i]->status == PL_THREAD_UNUSED || |
1421 | 1425 | GD->thread.threads[i]->status == PL_THREAD_RESERVED ) |
1422 | 1426 | return -1; /* error */ |
1456 | 1460 | return FALSE; /* illegal signal */ |
1457 | 1461 | |
1458 | 1462 | PL_LOCK(L_THREAD); |
1459 | for(i = 1; i <= thread_highest_id; i++) | |
1463 | for(i = 1; i <= GD->thread.highest_id; i++) | |
1460 | 1464 | { PL_thread_info_t *info = GD->thread.threads[i]; |
1461 | 1465 | |
1462 | 1466 | if ( info && info->w32id == id && info->thread_data ) |
1510 | 1514 | |
1511 | 1515 | int |
1512 | 1516 | PL_thread_raise(int tid, int sig) |
1513 | { if ( tid >= 1 && tid <= thread_highest_id ) | |
1517 | { if ( tid >= 1 && tid <= GD->thread.highest_id ) | |
1514 | 1518 | { PL_thread_info_t *info = GD->thread.threads[tid]; |
1515 | 1519 | |
1516 | 1520 | if ( info && |
1570 | 1574 | |
1571 | 1575 | for( ; mask ; mask <<= 1, sig++ ) |
1572 | 1576 | { if ( LD->signal.pending[i] & mask ) |
1573 | { __sync_and_and_fetch(&LD->signal.pending[i], ~mask); | |
1577 | { __atomic_and_fetch(&LD->signal.pending[i], ~mask, __ATOMIC_SEQ_CST); | |
1574 | 1578 | |
1575 | 1579 | if ( sig == SIG_THREAD_SIGNAL ) |
1576 | 1580 | { dispatch_signal(sig, TRUE); |
2150 | 2154 | } |
2151 | 2155 | |
2152 | 2156 | if ( i < 1 || |
2153 | i > thread_highest_id || | |
2157 | i > GD->thread.highest_id || | |
2154 | 2158 | THREAD_STATUS_INVALID(GD->thread.threads[i]->status) ) |
2155 | 2159 | { goto no_thread; |
2156 | 2160 | } |
2348 | 2352 | info->goal = NULL; |
2349 | 2353 | PL_UNLOCK(L_THREAD); |
2350 | 2354 | |
2351 | if ( info->pl_tid == thread_highest_id ) | |
2355 | if ( info->pl_tid == GD->thread.highest_id ) | |
2352 | 2356 | { int i; |
2353 | 2357 | |
2354 | 2358 | for(i=info->pl_tid-1; i>1; i--) |
2358 | 2362 | } |
2359 | 2363 | |
2360 | 2364 | /* do not update if alloc_thread() did */ |
2361 | COMPARE_AND_SWAP(&thread_highest_id, info->pl_tid, i); | |
2365 | COMPARE_AND_SWAP_INT(&GD->thread.highest_id, info->pl_tid, i); | |
2362 | 2366 | } |
2363 | 2367 | |
2364 | 2368 | do |
2365 | 2369 | { freelist = GD->thread.free; |
2366 | 2370 | info->next_free = freelist; |
2367 | } while( !COMPARE_AND_SWAP(&GD->thread.free, freelist, info) ); | |
2371 | } while( !COMPARE_AND_SWAP_PTR(&GD->thread.free, freelist, info) ); | |
2368 | 2372 | |
2369 | 2373 | if ( rec_rv ) PL_erase(rec_rv); |
2370 | 2374 | if ( rec_g ) PL_erase(rec_g); |
2437 | 2441 | |
2438 | 2442 | status = info->status; |
2439 | 2443 | if ( !THREAD_STATUS_INVALID(status) && |
2440 | COMPARE_AND_SWAP(&info->status, status, PL_THREAD_JOINED) ) | |
2444 | COMPARE_AND_SWAP_INT((int*)&info->status, (int)status, (int)PL_THREAD_JOINED) ) | |
2441 | 2445 | { rval = unify_thread_status(retcode, info, status, FALSE); |
2442 | 2446 | |
2443 | 2447 | free_thread_info(info); |
2521 | 2525 | } |
2522 | 2526 | |
2523 | 2527 | |
2528 | static size_t | |
2529 | sizeof_thread(PL_thread_info_t *info) | |
2530 | { size_t size = sizeof(*info); | |
2531 | struct PL_local_data *ld = info->thread_data; | |
2532 | ||
2533 | if ( info->status != PL_THREAD_RUNNING ) | |
2534 | return 0; | |
2535 | ||
2536 | if ( ld ) | |
2537 | { size += sizeof(*ld); | |
2538 | size += sizeStackP(&ld->stacks.global) + ld->stacks.global.spare; | |
2539 | size += sizeStackP(&ld->stacks.local) + ld->stacks.local.spare; | |
2540 | size += sizeStackP(&ld->stacks.trail) + ld->stacks.trail.spare; | |
2541 | size += sizeStackP(&ld->stacks.argument); | |
2542 | ||
2543 | size += sizeof_message_queue(&ld->thread.messages); | |
2544 | size += sizeof_local_definitions(ld); | |
2545 | ||
2546 | if ( ld->tabling.node_pool ) | |
2547 | size += ld->tabling.node_pool->size; | |
2548 | } | |
2549 | ||
2550 | return size; | |
2551 | } | |
2552 | ||
2553 | ||
2524 | 2554 | /******************************* |
2525 | 2555 | * THREAD PROPERTY * |
2526 | 2556 | *******************************/ |
2604 | 2634 | if ( tid != -1 ) |
2605 | 2635 | return PL_unify_integer(prop, system_thread_id(info)); |
2606 | 2636 | } |
2637 | ||
2638 | return FALSE; | |
2639 | } | |
2640 | ||
2641 | static int | |
2642 | thread_size_propery(PL_thread_info_t *info, term_t prop ARG_LD) | |
2643 | { size_t size; | |
2644 | ||
2645 | PL_LOCK(L_THREAD); | |
2646 | size = sizeof_thread(info); | |
2647 | PL_UNLOCK(L_THREAD); | |
2648 | ||
2649 | if ( size ) | |
2650 | return PL_unify_int64(prop, size); | |
2607 | 2651 | |
2608 | 2652 | return FALSE; |
2609 | 2653 | } |
2617 | 2661 | { FUNCTOR_engine1, thread_engine_propery }, |
2618 | 2662 | { FUNCTOR_thread1, thread_thread_propery }, |
2619 | 2663 | { FUNCTOR_system_thread_id1, thread_tid_propery }, |
2664 | { FUNCTOR_size1, thread_size_propery }, | |
2620 | 2665 | { 0, NULL } |
2621 | 2666 | }; |
2622 | 2667 | |
2641 | 2686 | if ( state->enum_threads ) |
2642 | 2687 | { do |
2643 | 2688 | { state->tid++; |
2644 | if ( state->tid > thread_highest_id ) | |
2689 | if ( state->tid > GD->thread.highest_id ) | |
2645 | 2690 | fail; |
2646 | 2691 | } while ( GD->thread.threads[state->tid]->status == PL_THREAD_UNUSED || |
2647 | 2692 | GD->thread.threads[state->tid]->status == PL_THREAD_RESERVED ); |
4063 | 4108 | if ( queue->max_size != 0 ) |
4064 | 4109 | cv_init(&queue->drain_var, NULL); |
4065 | 4110 | queue->initialized = TRUE; |
4111 | } | |
4112 | ||
4113 | ||
4114 | static size_t | |
4115 | sizeof_message_queue(message_queue *queue) | |
4116 | { size_t size = 0; | |
4117 | thread_message *msgp; | |
4118 | ||
4119 | simpleMutexLock(&queue->gc_mutex); | |
4120 | for( msgp = queue->head; msgp; msgp = msgp->next ) | |
4121 | { size += sizeof(*msgp); | |
4122 | size += msgp->message->size; | |
4123 | } | |
4124 | simpleMutexUnlock(&queue->gc_mutex); | |
4125 | ||
4126 | return size; | |
4066 | 4127 | } |
4067 | 4128 | |
4068 | 4129 | /* Prolog predicates */ |
4446 | 4507 | |
4447 | 4508 | if ( tid > 0 ) |
4448 | 4509 | { have_tid: |
4449 | if ( tid >= 1 && tid <= thread_highest_id ) | |
4510 | if ( tid >= 1 && tid <= GD->thread.highest_id ) | |
4450 | 4511 | { PL_thread_info_t *info = GD->thread.threads[tid]; |
4451 | 4512 | |
4452 | 4513 | if ( info->status == PL_THREAD_UNUSED || |
5410 | 5471 | static int |
5411 | 5472 | GCthread(void) |
5412 | 5473 | { if ( GC_id <= 0 ) |
5413 | { if ( COMPARE_AND_SWAP(&GC_starting, FALSE, TRUE) ) | |
5474 | { if ( COMPARE_AND_SWAP_INT(&GC_starting, FALSE, TRUE) ) | |
5414 | 5475 | { pthread_attr_t attr; |
5415 | 5476 | pthread_t thr; |
5416 | 5477 | int rc; |
6030 | 6091 | int me = PL_thread_self(); |
6031 | 6092 | int i; |
6032 | 6093 | |
6033 | for( i=1; i<=thread_highest_id; i++ ) | |
6094 | for( i=1; i<=GD->thread.highest_id; i++ ) | |
6034 | 6095 | { if ( i != me ) |
6035 | 6096 | { PL_thread_info_t *info = GD->thread.threads[i]; |
6036 | 6097 | |
6301 | 6362 | } |
6302 | 6363 | |
6303 | 6364 | |
6365 | static size_t | |
6366 | sizeof_local_definitions(PL_local_data_t *ld) | |
6367 | { DefinitionChain ch = ld->thread.local_definitions; | |
6368 | size_t size = 0; | |
6369 | ||
6370 | for( ; ch; ch = ch->next) | |
6371 | size += sizeof_predicate(ch->definition); | |
6372 | ||
6373 | return size; | |
6374 | } | |
6375 | ||
6376 | ||
6377 | ||
6304 | 6378 | /** '$thread_local_clause_count'(:Head, +Thread, -NumberOfClauses) is semidet. |
6305 | 6379 | |
6306 | 6380 | True when NumberOfClauses is the number of clauses for the thread-local |
6498 | 6572 | #ifdef O_PLMT |
6499 | 6573 | int i; |
6500 | 6574 | |
6501 | for(i=1; i<=thread_highest_id; i++) | |
6575 | for(i=1; i<=GD->thread.highest_id; i++) | |
6502 | 6576 | { PL_thread_info_t *info = GD->thread.threads[i]; |
6503 | 6577 | PL_local_data_t *ld = acquire_ldata(info); |
6504 | 6578 | |
6536 | 6610 | #ifdef O_PLMT |
6537 | 6611 | int i; |
6538 | 6612 | |
6539 | for(i=1; i<=thread_highest_id; i++) | |
6613 | for(i=1; i<=GD->thread.highest_id; i++) | |
6540 | 6614 | { PL_thread_info_t *info = GD->thread.threads[i]; |
6541 | 6615 | if ( info && info->access.kvs == kvs ) |
6542 | 6616 | { return TRUE; |
6558 | 6632 | #ifdef O_PLMT |
6559 | 6633 | int i; |
6560 | 6634 | |
6561 | for(i=1; i<=thread_highest_id; i++) | |
6635 | for(i=1; i<=GD->thread.highest_id; i++) | |
6562 | 6636 | { PL_thread_info_t *info = GD->thread.threads[i]; |
6563 | 6637 | if ( info && info->access.atom_table == atom_table ) |
6564 | 6638 | { return TRUE; |
6576 | 6650 | #ifdef O_PLMT |
6577 | 6651 | int i; |
6578 | 6652 | |
6579 | for(i=1; i<=thread_highest_id; i++) | |
6653 | for(i=1; i<=GD->thread.highest_id; i++) | |
6580 | 6654 | { PL_thread_info_t *info = GD->thread.threads[i]; |
6581 | 6655 | if ( info && info->access.atom_bucket == bucket ) |
6582 | 6656 | { return TRUE; |
6593 | 6667 | ldata_in_use(PL_local_data_t *ld) |
6594 | 6668 | { int i; |
6595 | 6669 | |
6596 | for(i=1; i<=thread_highest_id; i++) | |
6670 | for(i=1; i<=GD->thread.highest_id; i++) | |
6597 | 6671 | { PL_thread_info_t *info = GD->thread.threads[i]; |
6598 | 6672 | if ( info && info->access.ldata == ld ) |
6599 | 6673 | { return TRUE; |
6615 | 6689 | Atom **buckets = allocHeapOrHalt(sz * sizeof(Atom*)); |
6616 | 6690 | memset(buckets, 0, sz * sizeof(Atom*)); |
6617 | 6691 | |
6618 | for(i=1; i<=thread_highest_id; i++) | |
6692 | for(i=1; i<=GD->thread.highest_id; i++) | |
6619 | 6693 | { PL_thread_info_t *info = GD->thread.threads[i]; |
6620 | 6694 | if ( info && info->access.atom_bucket ) |
6621 | 6695 | { if ( index >= sz-1 ) |
6653 | 6727 | Definition *buckets = allocHeapOrHalt(sz * sizeof(Definition)); |
6654 | 6728 | memset(buckets, 0, sz * sizeof(Definition*)); |
6655 | 6729 | |
6656 | for(i=1; i<=thread_highest_id; i++) | |
6730 | for(i=1; i<=GD->thread.highest_id; i++) | |
6657 | 6731 | { PL_thread_info_t *info = GD->thread.threads[i]; |
6658 | 6732 | if ( info && info->access.predicate ) |
6659 | 6733 | { if ( index >= sz-1 ) |
6692 | 6766 | int me = PL_thread_self(); |
6693 | 6767 | int i; |
6694 | 6768 | |
6695 | for(i=1; i<=thread_highest_id; i++) | |
6769 | for(i=1; i<=GD->thread.highest_id; i++) | |
6696 | 6770 | { PL_thread_info_t *info = GD->thread.threads[i]; |
6697 | 6771 | if ( i != me && info && info->access.functor_table == functor_table ) |
6698 | 6772 | { return TRUE; |
6761 | 6835 | outOfCore(); |
6762 | 6836 | |
6763 | 6837 | memset(newblock, 0, bs*sizeof(definition_ref)); |
6764 | if ( !COMPARE_AND_SWAP(&refs->blocks[idx], NULL, newblock-bs) ) | |
6838 | if ( !COMPARE_AND_SWAP_PTR(&refs->blocks[idx], NULL, newblock-bs) ) | |
6765 | 6839 | PL_free(newblock); |
6766 | 6840 | } |
6767 | 6841 |
212 | 212 | { atom_t dbref; |
213 | 213 | |
214 | 214 | if ( (dbref=trie->clause) ) |
215 | { if ( COMPARE_AND_SWAP(&trie->clause, dbref, 0) && | |
215 | { if ( COMPARE_AND_SWAP_WORD(&trie->clause, dbref, 0) && | |
216 | 216 | GD->cleaning == CLN_NORMAL ) /* otherwise reclaims clause */ |
217 | 217 | { ClauseRef cref = clause_clref(dbref); /* from two ends */ |
218 | 218 | |
235 | 235 | { indirect_table *it = trie->indirects; |
236 | 236 | |
237 | 237 | clear_node(trie, &trie->root, FALSE); /* TBD: verify not accessed */ |
238 | if ( it && COMPARE_AND_SWAP(&trie->indirects, it, NULL) ) | |
238 | if ( it && COMPARE_AND_SWAP_PTR(&trie->indirects, it, NULL) ) | |
239 | 239 | destroy_indirect_table(it); |
240 | 240 | trie->node_count = 1; |
241 | 241 | trie->value_count = 0; |
366 | 366 | if ( children.any ) |
367 | 367 | { switch( children.any->type ) |
368 | 368 | { case TN_KEY: |
369 | if ( COMPARE_AND_SWAP(&p->children.any, children.any, NULL) ) | |
369 | if ( COMPARE_AND_SWAP_PTR(&p->children.any, children.any, NULL) ) | |
370 | 370 | PL_free(children.any); |
371 | 371 | break; |
372 | 372 | case TN_HASHED: |
445 | 445 | if ( children.any ) |
446 | 446 | { switch( children.any->type ) |
447 | 447 | { case TN_KEY: |
448 | if ( COMPARE_AND_SWAP(&p->children.any, children.any, NULL) ) | |
448 | if ( COMPARE_AND_SWAP_PTR(&p->children.any, children.any, NULL) ) | |
449 | 449 | PL_free(children.any); |
450 | 450 | break; |
451 | 451 | case TN_HASHED: |
548 | 548 | update_var_mask(hnode, new->key); |
549 | 549 | new->parent = n; |
550 | 550 | |
551 | if ( COMPARE_AND_SWAP(&n->children.hash, children.hash, hnode) ) | |
551 | if ( COMPARE_AND_SWAP_PTR(&n->children.hash, children.hash, hnode) ) | |
552 | 552 | { hnode->old_single = children.key; /* See (*) */ |
553 | 553 | return new; |
554 | 554 | } else |
587 | 587 | child->key = key; |
588 | 588 | child->child = new; |
589 | 589 | |
590 | if ( COMPARE_AND_SWAP(&n->children.key, NULL, child) ) | |
590 | if ( COMPARE_AND_SWAP_PTR(&n->children.key, NULL, child) ) | |
591 | 591 | { child->child->parent = n; |
592 | 592 | return child->child; |
593 | 593 | } |
620 | 620 | } else if ( add ) |
621 | 621 | { indirect_table *newtab = new_indirect_table(); |
622 | 622 | |
623 | if ( !COMPARE_AND_SWAP(&trie->indirects, NULL, newtab) ) | |
623 | if ( !COMPARE_AND_SWAP_PTR(&trie->indirects, NULL, newtab) ) | |
624 | 624 | destroy_indirect_table(newtab); |
625 | 625 | } else |
626 | 626 | { return 0; |
2340 | 2340 | } else if ( name == ATOM_reevaluated && (idg=trie->data.IDG)) |
2341 | 2341 | { return PL_unify_int64(arg, idg->stats.reevaluated); |
2342 | 2342 | #endif |
2343 | } else if ( (idg=trie->data.IDG) ) | |
2344 | { if ( name == ATOM_idg_affected_count ) | |
2345 | { return PL_unify_int64(arg, idg->affected ? idg->affected->size : 0); | |
2346 | } else if ( name == ATOM_idg_dependent_count ) | |
2347 | { return PL_unify_int64(arg, idg->dependent ? idg->dependent->size : 0); | |
2348 | } else if ( name == ATOM_idg_size ) | |
2349 | { size_t size = sizeof(*idg); | |
2350 | ||
2351 | if ( idg->affected ) size += sizeofTable(idg->affected); | |
2352 | if ( idg->dependent ) size += sizeofTable(idg->dependent); | |
2353 | ||
2354 | return PL_unify_int64(arg, size); | |
2355 | } | |
2343 | 2356 | } |
2344 | 2357 | } |
2345 | 2358 | } |
2853 | 2866 | if ( !(dbref = trie->clause) ) |
2854 | 2867 | { if ( trie->value_count == 0 ) |
2855 | 2868 | { dbref = ATOM_fail; |
2856 | if ( !COMPARE_AND_SWAP(&trie->clause, 0, dbref) ) | |
2869 | if ( !COMPARE_AND_SWAP_WORD(&trie->clause, 0, dbref) ) | |
2857 | 2870 | goto retry; |
2858 | 2871 | } else |
2859 | 2872 | { trie_compile_state state; |
2867 | 2880 | { cref = assertDefinition(def, cl, CL_END PASS_LD); |
2868 | 2881 | if ( cref ) |
2869 | 2882 | { dbref = lookup_clref(cref->value.clause); |
2870 | if ( !COMPARE_AND_SWAP(&trie->clause, 0, dbref) ) | |
2883 | if ( !COMPARE_AND_SWAP_WORD(&trie->clause, 0, dbref) ) | |
2871 | 2884 | { PL_unregister_atom(dbref); |
2872 | 2885 | retractClauseDefinition(def, cref->value.clause); |
2873 | 2886 | goto retry; |
302 | 302 | |
303 | 303 | do |
304 | 304 | { alerted = ld->alerted; |
305 | } while ( !COMPARE_AND_SWAP(&ld->alerted, alerted, alerted|ALERT_SIGNAL) ); | |
305 | } while ( !COMPARE_AND_SWAP_INT(&ld->alerted, alerted, alerted|ALERT_SIGNAL) ); | |
306 | 306 | |
307 | 307 | return TRUE; |
308 | 308 | } |
1395 | 1395 | outOfCore(); |
1396 | 1396 | |
1397 | 1397 | memset(newblock, 0, bs*sizeof(Definition)); |
1398 | if ( !COMPARE_AND_SWAP(&v->blocks[idx], NULL, newblock-bs) ) | |
1398 | if ( !COMPARE_AND_SWAP_PTR(&v->blocks[idx], NULL, newblock-bs) ) | |
1399 | 1399 | PL_free(newblock); |
1400 | 1400 | } |
1401 | 1401 | } |
339 | 339 | |
340 | 340 | static bool |
341 | 341 | Putc(int c, IOSTREAM *s) |
342 | { return Sputcode(c, s) == EOF ? FALSE : TRUE; | |
342 | { return Sputcode(c, s) != EOF; | |
343 | 343 | } |
344 | 344 | |
345 | 345 | |
814 | 814 | writeString(term_t t, write_options *options) |
815 | 815 | { GET_LD |
816 | 816 | PL_chars_t txt; |
817 | int rc = TRUE; | |
817 | 818 | |
818 | 819 | PL_get_text(t, &txt, CVT_STRING); |
820 | if ( txt.storage != PL_CHARS_LOCAL ) | |
821 | PL_save_text(&txt, BUF_MALLOC); | |
819 | 822 | |
820 | 823 | if ( true(options, PL_WRT_QUOTED) ) |
821 | 824 | { int quote; |
826 | 829 | else |
827 | 830 | quote = '"'; |
828 | 831 | |
829 | TRY(Putc(quote, options->out)); | |
832 | if ( !(rc=Putc(quote, options->out)) ) | |
833 | goto out; | |
830 | 834 | |
831 | 835 | for(i=0; i<txt.length; i++) |
832 | 836 | { int chr = get_chr_from_text(&txt, i); |
833 | 837 | |
834 | TRY(putQuoted(chr, quote, options->flags, options->out)); | |
835 | } | |
836 | ||
837 | return Putc(quote, options->out); | |
838 | if ( !(rc=putQuoted(chr, quote, options->flags, options->out)) ) | |
839 | goto out; | |
840 | } | |
841 | ||
842 | rc = Putc(quote, options->out); | |
838 | 843 | } else |
839 | 844 | { unsigned int i; |
840 | 845 | |
841 | 846 | for(i=0; i<txt.length; i++) |
842 | 847 | { int chr = get_chr_from_text(&txt, i); |
843 | 848 | |
844 | TRY(Putc(chr, options->out)); | |
845 | } | |
846 | } | |
847 | ||
848 | succeed; | |
849 | if ( !(rc=Putc(chr, options->out)) ) | |
850 | break; | |
851 | } | |
852 | } | |
853 | ||
854 | out: | |
855 | PL_free_text(&txt); | |
856 | ||
857 | return rc; | |
849 | 858 | } |
850 | 859 | |
851 | 860 | #endif /*O_STRING*/ |
2917 | 2917 | |
2918 | 2918 | run_pkg_test1(Script, Goal, PkgDir) :- |
2919 | 2919 | current_prolog_flag(executable, SWIPL), |
2920 | working_directory(CWD, CWD), | |
2921 | format(atom(POpt), 'test_tmp_dir=~w', [CWD]), | |
2920 | 2922 | process_create(SWIPL, |
2921 | 2923 | [ '-f', 'none', |
2922 | 2924 | '-t', 'halt', |
2925 | '--no-packs', | |
2926 | '-p', POpt, | |
2923 | 2927 | '-g', Goal, |
2924 | 2928 | Script |
2925 | 2929 | ], |