Update upstream source from tag 'upstream/8.0.2+dfsg'
Update to upstream version '8.0.2+dfsg'
with Debian dir a456e637649e80b26b2cd9ae5973911328af66cf
Lev Lamberov
5 years ago
33 | 33 | |
34 | 34 | ### Getting the source |
35 | 35 | |
36 | The source imay be downloaded as a tar ball from | |
37 | http://www.swi-prolog.org or downloaded using git. The git sequencen is: | |
36 | The source may be downloaded as a tar ball from | |
37 | http://www.swi-prolog.org or downloaded using git. The git sequence is: | |
38 | 38 | |
39 | 39 | git clone https://github.com/SWI-Prolog/swipl-devel.git |
40 | cd swipl-devel | |
40 | 41 | git submodule update --init |
42 | ||
43 | If not all modules are needed, one can clone/update particular ones as follows: | |
44 | ||
45 | git submodule update --init packages/jpl packages/clib packages/sgml | |
41 | 46 | |
42 | 47 | |
43 | 48 | ### Building from source |
78 | 83 | The default build type is `RelWithDebInfo`. Alternatives may be selected |
79 | 84 | using e.g., |
80 | 85 | |
81 | cmake -DCMAKE_BUILD_TYPE=Debug | |
82 | cmake -DCMAKE_BUILD_TYPE=Release | |
86 | cmake -DCMAKE_BUILD_TYPE=Debug -G Ninja .. | |
87 | cmake -DCMAKE_BUILD_TYPE=Release -G Ninja .. | |
88 | ||
89 | ## Install location | |
90 | ||
91 | To install in a particular location, use `-DCMAKE_INSTALL_PREFIX:PATH=/path/to/install`. For example, this will build SWI to be installed in `/usr/local/swipl-git` and will not include the documentation (see below for other customization options): | |
92 | ||
93 | cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr/local/swipl-git -DINSTALL_DOCUMENTATION=OFF .. | |
94 | ||
95 | After `sudo make install`, SWI will be located in `/usr/local/swipl-git`. Next adapt environment variables `SWI_HOME_DIR` and `LD_LIBRARY_PATH` to point to the new compiled and installed SWI system: | |
96 | ||
97 | export SWI_HOME_DIR=/usr/local/swipl-git/lib/swipl/ | |
98 | export LD_LIBRARY_PATH=/usr/local/swipl-git/lib/swipl/lib/x86_64-linux/:$LD_LIBRARY_PATH | |
99 | ||
100 | Finally, you can run it: | |
101 | ||
102 | /usr/local/swipl-git/bin/swipl | |
103 | ||
104 | _NOTE:_ if there is already an installed SWI (e.g., the one coming with a Linux distribution), running `swipl` will run the new installed system pointed by `SWI_HOME_DIR`. | |
105 | ||
83 | 106 | |
84 | 107 | ## Customizing SWI-Prolog |
85 | 108 | |
349 | 372 | |
350 | 373 | ## Issues |
351 | 374 | |
352 | - Provide a FindSWIPL.cmake? | |
375 | - Provide a FindSWIPL.cmake? | |
376 | - Problem compiling SWI when another SWI is installed already and you | |
377 | have environment variables set to facilitate e.g., embedding in Java. | |
378 | The variable names and possibly conflicting values depend on the OS. | |
379 | See [issue](https://github.com/SWI-Prolog/swipl-devel/issues/435) | |
380 | ||
381 | ||
382 | ||
383 | ||
384 |
2 | 2 | |
3 | 3 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") |
4 | 4 | set(CMAKE_POLICY_DEFAULT_CMP0075 NEW) |
5 | set(CMAKE_POLICY_DEFAULT_CMP0074 NEW) | |
5 | 6 | |
6 | 7 | option(MULTI_THREADED |
7 | 8 | "Enable multiple Prolog threads" |
166 | 166 | |
167 | 167 | '$hide'(Pred) :- |
168 | 168 | '$set_predicate_attribute'(Pred, trace, false). |
169 | ||
170 | :- '$iso'(((dynamic)/1, (multifile)/1, (discontiguous)/1)). | |
169 | 171 | |
170 | 172 | |
171 | 173 | /******************************** |
3587 | 3589 | '$convert_option_value'(integer, String, Value) :- |
3588 | 3590 | ( number_string(Value, String) |
3589 | 3591 | -> true |
3592 | ; sub_string(String, 0, _, 1, SubString), | |
3593 | sub_string(String, _, 1, 0, Suffix0), | |
3594 | downcase_atom(Suffix0, Suffix), | |
3595 | number_string(Number, SubString), | |
3596 | '$suffix_multiplier'(Suffix, Multiplier) | |
3597 | -> Value is Number * Multiplier | |
3590 | 3598 | ; '$domain_error'(integer, String) |
3591 | 3599 | ). |
3592 | 3600 | '$convert_option_value'(callable, String, Value) :- |
3599 | 3607 | atom_string(Value, String). |
3600 | 3608 | '$convert_option_value'(ground, String, Value) :- |
3601 | 3609 | atom_string(Value, String). |
3610 | ||
3611 | '$suffix_multiplier'(b, 1). | |
3612 | '$suffix_multiplier'(k, 1024). | |
3613 | '$suffix_multiplier'(m, 1024 * 1024). | |
3614 | '$suffix_multiplier'(g, 1024 * 1024 * 1024). | |
3602 | 3615 | |
3603 | 3616 | |
3604 | 3617 | /******************************* |
761 | 761 | * GC * |
762 | 762 | *******************************/ |
763 | 763 | |
764 | prolog_message(gc(start)) --> | |
765 | thread_context, | |
766 | [ 'GC: ', flush ]. | |
767 | prolog_message(gc(done(G, T, Time, UG, UT, RG, RT))) --> | |
768 | [ at_same_line, | |
769 | 'gained ~D+~D in ~3f sec; used ~D+~D; free ~D+~D'- | |
770 | [G, T, Time, UG, UT, RG, RT] | |
771 | ]. | |
772 | prolog_message(shift_stacks(start(_L,_G,_T))) --> | |
773 | thread_context, | |
774 | [ 'Stack-shift: ', flush ]. | |
775 | prolog_message(shift_stacks(done(Time, L, G, T))) --> | |
776 | { LKB is L//1024, | |
777 | GKB is G//1024, | |
778 | TKB is T//1024 | |
779 | }, | |
780 | [ at_same_line, | |
781 | 'local: ~DKB, global: ~DKB, trail: ~DKB bytes (~2f sec)'- | |
782 | [LKB, GKB, TKB, Time] | |
783 | ]. | |
784 | 764 | prolog_message(agc(start)) --> |
785 | 765 | thread_context, |
786 | 766 | [ 'AGC: ', flush ]. |
332 | 332 | { atom(Name), integer(Arity), Arity >= 0, |
333 | 333 | !, |
334 | 334 | functor(Head, Name, Arity), |
335 | check_undefined(Name/Arity), | |
335 | 336 | atom_concat(Name, ' tabled', WrapName), |
336 | 337 | Head =.. [Name|Args], |
337 | 338 | WrappedHead =.. [WrapName|Args], |
349 | 350 | !, |
350 | 351 | functor(ModeDirectedSpec, Name, Arity), |
351 | 352 | functor(Head, Name, Arity), |
353 | check_undefined(Name/Arity), | |
352 | 354 | atom_concat(Name, ' tabled', WrapName), |
353 | 355 | Head =.. [Name|Args], |
354 | 356 | WrappedHead =.. [WrapName|Args], |
372 | 374 | { '$type_error'(table_desclaration, TableSpec) |
373 | 375 | }. |
374 | 376 | |
377 | %! check_undefined(+PI) | |
378 | % | |
379 | % Verify the predicate has no clauses when the :- table is declared. | |
380 | % | |
381 | % @tbd: future versions may rename the existing predicate. | |
382 | ||
383 | check_undefined(Name/Arity) :- | |
384 | functor(Head, Name, Arity), | |
385 | prolog_load_context(module, Module), | |
386 | clause(Module:Head, _), | |
387 | !, | |
388 | '$permission_error'(table, procedure, Name/Arity). | |
389 | check_undefined(_). | |
390 | ||
375 | 391 | %! mode_check(+Moded, -TestCode) |
376 | 392 | % |
377 | 393 | % Enforce the output arguments of a mode-directed tabled predicate to |
24 | 24 | REGEX "^DOUBLE_ALIGNMENT=${alignof_pat_regex}" LIMIT_COUNT 1) |
25 | 25 | |
26 | 26 | # Extract alignments from patterns and assign them to the variables |
27 | string(REGEX MATCH "${alignof_pat_regex}$" int64_alignment ${alignof_int64_pat}) | |
28 | string(REGEX MATCH "${alignof_pat_regex}$" double_alignment ${alignof_double_pat}) | |
29 | string(REGEX MATCH "${alignof_pat_regex}$" voidp_alignment ${alignof_voidp_pat}) | |
27 | string(REGEX MATCH "${alignof_pat_regex}$" int64_alignment "${alignof_int64_pat}") | |
28 | string(REGEX MATCH "${alignof_pat_regex}$" double_alignment "${alignof_double_pat}") | |
29 | string(REGEX MATCH "${alignof_pat_regex}$" voidp_alignment "${alignof_voidp_pat}") | |
30 | 30 | |
31 | 31 | # Cache the results |
32 | 32 | set(${VAR_ALIGNOF_INT64_T} ${int64_alignment} CACHE STRING "Alignment of int64_t") |
22 | 22 | |
23 | 23 | int prevent_optimization(unsigned char*p, int size) { |
24 | 24 | unsigned char *d; |
25 | int i; | |
25 | 26 | |
26 | 27 | //Prevent optimizer from eliminating the constants in main() |
27 | 28 | unsigned char dummy[size]; |
28 | 29 | d = dummy; |
29 | for (int i = 0; i < size; ++i) { | |
30 | for (i = 0; i < size; ++i) { | |
30 | 31 | *d++ = *p++; |
31 | 32 | } |
32 | 33 | return dummy[size-1]; |
0 | 0 | function(conflicting_var name) |
1 | 1 | message(WARNING |
2 | "-- $${name} is set to $ENV{${name}}\n" | |
2 | "-- Environment variable ${name} is set to $ENV{${name}}\n" | |
3 | "This suggests that the variable is referring to a existing installation of SWI-Prolog. " | |
3 | 4 | "This may conflict with building SWI-Prolog as this may cause the " |
4 | "build process to use components from an older installed version " | |
5 | "build process to use components from such (older) installed version " | |
5 | 6 | "of SWI-Prolog. Make sure to remove this environment from the " |
6 | 7 | "environment before building the system.") |
7 | 8 | endfunction() |
8 | 9 | |
9 | 10 | if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF" AND |
10 | NOT x"$ENV{LD_PRELOAD}" STREQUAL x AND | |
11 | "$ENV{LD_PRELOAD}" MATCHES swipl) | |
11 | DEFINED ENV{LD_PRELOAD} AND | |
12 | "$ENV{LD_PRELOAD}" MATCHES swipl|swi-prolog) | |
12 | 13 | conflicting_var(LD_PRELOAD) |
13 | 14 | endif() |
14 | 15 | |
15 | 16 | if(UNIX) |
16 | 17 | if(APPLE) |
17 | if(NOT x"$ENV{DYLD_LIBRARY_PATH}" STREQUAL x AND | |
18 | "$ENV{DYLD_LIBRARY_PATH}" MATCHES swipl) | |
18 | if(DEFINED ENV{DYLD_LIBRARY_PATH} AND | |
19 | "$ENV{DYLD_LIBRARY_PATH}" MATCHES swipl|swi-prolog) | |
19 | 20 | conflicting_var(DYLD_LIBRARY_PATH) |
20 | 21 | endif() |
21 | 22 | else() |
22 | if(NOT x"$ENV{LD_LIBRARY_PATH}" STREQUAL x AND | |
23 | "$ENV{LD_LIBRARY_PATH}" MATCHES swipl) | |
24 | conflicting_var(DYLD_LIBRARY_PATH) | |
23 | if(DEFINED ENV{LD_LIBRARY_PATH} AND | |
24 | "$ENV{LD_LIBRARY_PATH}" MATCHES swipl|swi-prolog) | |
25 | conflicting_var(LD_LIBRARY_PATH) | |
25 | 26 | endif() |
26 | 27 | endif() |
27 | 28 | elseif(WIN32) |
28 | if(NOT x"$ENV{PATH}" STREQUAL x AND | |
29 | "$ENV{PATH}" MATCHES swipl) | |
29 | if(DEFINED ENV{PATH} AND | |
30 | "$ENV{PATH}" MATCHES swipl|swi-prolog) | |
30 | 31 | conflicting_var(PATH) |
31 | 32 | endif() |
32 | 33 | endif() |
33 | 34 | |
34 | if(NOT x"$ENV{SWI_HOME_DIR}" STREQUAL x AND | |
35 | IS_DIRECTORY "$ENV{SWIPL}") | |
35 | if(DEFINED ENV{SWI_HOME_DIR} AND | |
36 | IS_DIRECTORY "$ENV{SWI_HOME_DIR}") | |
36 | 37 | conflicting_var(SWI_HOME_DIR) |
37 | 38 | endif() |
38 | if(NOT "$ENV{SWIPL}" STREQUAL x AND | |
39 | if(DEFINED ENV{SWIPL} AND | |
39 | 40 | IS_DIRECTORY "$ENV{SWIPL}") |
40 | 41 | conflicting_var(SWIPL) |
41 | 42 | endif() |
30 | 30 | -s WASM=1 |
31 | 31 | -s MODULARIZE=1 |
32 | 32 | -s EXPORT_NAME=SWIPL |
33 | -s BINARYEN_METHOD='native-wasm' | |
34 | 33 | -s BINARYEN_TRAP_MODE=clamp |
35 | 34 | -s NO_EXIT_RUNTIME=0 |
36 | 35 | -s EXPORTED_FUNCTIONS=@${CMAKE_SOURCE_DIR}/src/wasm/exports.json |
55 | 55 | endif() |
56 | 56 | endif() |
57 | 57 | |
58 | # see https://crascit.com/2015/08/07/cmake_cpack_nsis_shortcuts_with_parameters/ | |
59 | ||
58 | 60 | if(WIN32) |
61 | set(CPACK_NSIS_CREATE_ICONS_EXTRA "") | |
62 | ||
63 | function(createShortCut name exe options desktop) | |
64 | set(CPACK_NSIS_CREATE_ICONS_EXTRA | |
65 | "${CPACK_NSIS_CREATE_ICONS_EXTRA}\n CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${name}.lnk' '$INSTDIR\\\\bin\\\\${exe}.exe' '${options}'") | |
66 | set(CPACK_NSIS_DELETE_ICONS_EXTRA | |
67 | "${CPACK_NSIS_DELETE_ICONS_EXTRA}\n Delete '$SMPROGRAMS\\\\$START_MENU\\\\${name}.lnk'") | |
68 | if(desktop) | |
69 | set(CPACK_NSIS_CREATE_ICONS_EXTRA | |
70 | "${CPACK_NSIS_CREATE_ICONS_EXTRA}\n StrCmp '$INSTALL_DESKTOP' '1' 0 +2\n CreateShortCut '$DESKTOP\\\\${name}.lnk' '$INSTDIR\\\\bin\\\\${exe}.exe' '${options}'") | |
71 | set(CPACK_NSIS_DELETE_ICONS_EXTRA | |
72 | "${CPACK_NSIS_DELETE_ICONS_EXTRA}\n Delete '$DESKTOP\\\\${name}.lnk'") | |
73 | endif() | |
74 | ||
75 | set(CPACK_NSIS_CREATE_ICONS_EXTRA "${CPACK_NSIS_CREATE_ICONS_EXTRA}" PARENT_SCOPE) | |
76 | set(CPACK_NSIS_DELETE_ICONS_EXTRA "${CPACK_NSIS_DELETE_ICONS_EXTRA}" PARENT_SCOPE) | |
77 | endfunction() | |
78 | ||
59 | 79 | set(CPACK_PACKAGE_INSTALL_DIRECTORY swipl) |
60 | 80 | |
61 | 81 | set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) |
63 | 83 | set(CPACK_NSIS_DISPLAY_NAME "SWI-Prolog ${CPACK_PACKAGE_VERSION}") |
64 | 84 | set(CPACK_NSIS_URL_INFO_ABOUT "http://swi-prolog.org") |
65 | 85 | set(CPACK_NSIS_INSTALLED_ICON_NAME bin\\\\swipl-win.exe) |
66 | # does not work | |
67 | # set(CPACK_NSIS_DEFINES " !define MUI_STARTMENUPAGE_DEFAULTFOLDER \\\"SWI-Prolog\\\"") | |
86 | ||
87 | createShortCut("SWI-Prolog" "swipl-win" "--win_app" ON) | |
88 | createShortCut("SWI-Prolog (console)" "swipl" "" OFF) | |
68 | 89 | endif() |
69 | 90 | |
70 | 91 | set(CPACK_PACKAGE_FILE_NAME |
92 | 92 | set(PROG_SWIPL_FOR_BOOT $<TARGET_FILE:swipl>) |
93 | 93 | endif() |
94 | 94 | else() |
95 | set(PROG_SWIPL $<TARGET_FILE:swipl> | |
95 | set(PROG_SWIPL_TARGET_FILE $<TARGET_FILE:swipl> | |
96 | 96 | CACHE STRING "SWI-Prolog executable to perform build tasks") |
97 | set(PROG_SWIPL ${CMAKE_CROSSCOMPILING_EMULATOR} ${PROG_SWIPL_TARGET_FILE}) | |
97 | 98 | set(PROG_SWIPL_FOR_BOOT ${PROG_SWIPL}) |
98 | 99 | endif() |
99 | 100 | else(CMAKE_CROSSCOMPILING) |
45 | 45 | if(BUILD_MACOS_BUNDLE) |
46 | 46 | set(MACOS_APP "SWI-Prolog") |
47 | 47 | |
48 | set(X11_ROOT /opt/X11) | |
49 | set(Freetype_ROOT /opt/X11) | |
50 | set(FontConfig_ROOT /opt/X11) | |
51 | ||
48 | 52 | find_package(Qt5 COMPONENTS Widgets REQUIRED) |
49 | 53 | |
50 | 54 | get_target_property(uic_location Qt5::uic IMPORTED_LOCATION) |
0 | 0 | # We could set set linker flags for all excutables if we |
1 | 1 | # could override them for the browser binary. |
2 | 2 | #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ASSERTIONS=2 -s NODERAWFS=1 -s EXIT_RUNTIME=1") |
3 | ||
4 | # AlignOf.cmake doesn't work for Emscripten | |
5 | set(ALIGNOF_INT64_T 8 CACHE STRING "Alignment for int64_t") | |
6 | set(ALIGNOF_VOIDP ${SIZEOF_VOIDP} CACHE STRING "Alignment for pointers") | |
7 | set(ALIGNOF_DOUBLE 8 CACHE STRING "Alignment for double") |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org/projects/xpce/ |
5 | Copyright (c) 2011-2018, University of Amsterdam | |
5 | Copyright (c) 2011-2019, 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 |
1716 | 1717 | [ MP, |
1717 | 1718 | term_position(_,_,FF,FT,ArgPos) |
1718 | 1719 | ])) :- |
1720 | compound(Head), | |
1719 | 1721 | !, |
1720 | 1722 | colourise_module(M, TB, MP), |
1721 | 1723 | colour_item(functor, TB, QF-QT), |
1722 | 1724 | colour_item(goal(extern(M),Head), TB, FF-FT), |
1723 | Head =.. [_|Args], | |
1725 | compound_name_arguments(Head, _, Args), | |
1724 | 1726 | colourise_meta_decls(Args, Extra, TB, ArgPos). |
1725 | 1727 | colourise_meta_declaration(Head, Extra, TB, term_position(_,_,FF,FT,ArgPos)) :- |
1728 | compound(Head), | |
1726 | 1729 | !, |
1727 | 1730 | goal_classification(TB, Head, [], Class), |
1728 | 1731 | colour_item(goal(Class, Head), TB, FF-FT), |
1729 | Head =.. [_|Args], | |
1732 | compound_name_arguments(Head, _, Args), | |
1730 | 1733 | colourise_meta_decls(Args, Extra, TB, ArgPos). |
1731 | 1734 | colourise_meta_declaration([H|T], Extra, TB, list_position(LF,LT,[HP],TP)) :- |
1732 | 1735 | !, |
1438 | 1438 | ). |
1439 | 1439 | |
1440 | 1440 | pack_remove_forced(Pack) :- |
1441 | '$pack_detach'(Pack, BaseDir), | |
1441 | catch('$pack_detach'(Pack, BaseDir), | |
1442 | error(existence_error(pack, Pack), _), | |
1443 | fail), | |
1444 | !, | |
1442 | 1445 | print_message(informational, pack(remove(BaseDir))), |
1443 | 1446 | delete_directory_and_contents(BaseDir). |
1447 | pack_remove_forced(Pack) :- | |
1448 | directory_file_path(Pack, 'pack.pl', PackFile), | |
1449 | absolute_file_name(pack(PackFile), PackPath, | |
1450 | [ access(read), | |
1451 | file_errors(fail) | |
1452 | ]), | |
1453 | !, | |
1454 | file_directory_name(PackPath, BaseDir), | |
1455 | delete_directory_and_contents(BaseDir). | |
1456 | pack_remove_forced(Pack) :- | |
1457 | print_message(informational, error(existence_error(pack, Pack),_)). | |
1444 | 1458 | |
1445 | 1459 | confirm_remove(Pack, Deps, Delete) :- |
1446 | 1460 | print_message(warning, pack(depends(Pack, Deps))), |
283 | 283 | save_toplevel_goal(Out, _Default, Options) :- |
284 | 284 | option(toplevel(Goal), Options), |
285 | 285 | !, |
286 | format(Out, 'toplevel=~q~n', [Goal]). | |
286 | unqualify_reserved_goal(Goal, Goal1), | |
287 | format(Out, 'toplevel=~q~n', [Goal1]). | |
287 | 288 | save_toplevel_goal(Out, _Default, _Options) :- |
288 | 289 | '$cmd_option_val'(toplevel, Toplevel), |
289 | 290 | Toplevel \== default, |
291 | 292 | format(Out, 'toplevel=~w~n', [Toplevel]). |
292 | 293 | save_toplevel_goal(Out, Default, _Options) :- |
293 | 294 | format(Out, 'toplevel=~q~n', [Default]). |
295 | ||
296 | unqualify_reserved_goal(_:prolog, prolog) :- !. | |
297 | unqualify_reserved_goal(_:default, default) :- !. | |
298 | unqualify_reserved_goal(Goal, Goal). | |
294 | 299 | |
295 | 300 | |
296 | 301 | /******************************* |
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-2016, VU University Amsterdam | |
5 | Copyright (c) 2013-2019, 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 |
537 | 538 | safe_primitive(=\=(_,_)). |
538 | 539 | safe_primitive(=<(_,_)). |
539 | 540 | safe_primitive(<(_,_)). |
541 | safe_primitive(system:nth_integer_root_and_remainder(_,_,_,_)). | |
542 | ||
540 | 543 | % term-handling |
541 | 544 | safe_primitive(arg(_,_,_)). |
542 | 545 | safe_primitive(system:setarg(_,_,_)). |
701 | 704 | safe_primitive(system:nb_getval(_,_)). |
702 | 705 | safe_primitive('$syspreds':nb_setval(Var,_)) :- |
703 | 706 | safe_global_var(Var). |
707 | safe_primitive(system:nb_linkval(Var,_)) :- | |
708 | safe_global_var(Var). | |
704 | 709 | safe_primitive(system:nb_current(_,_)). |
705 | 710 | % database |
706 | 711 | safe_primitive(system:assert(X)) :- |
58 | 58 | |
59 | 59 | \newcommand{\vmajor}{8} |
60 | 60 | \newcommand{\vminor}{0} |
61 | \newcommand{\vpatch}{1} | |
61 | \newcommand{\vpatch}{2} | |
62 | 62 | \newcommand{\vtag}{} |
63 | \newcommand{\vmonth}{January} | |
63 | \newcommand{\vmonth}{March} | |
64 | 64 | \newcommand{\vyear}{2019} |
65 | 65 | |
66 | 66 | #ifdef BOOK |
2548 | 2548 | and class names\footnote{Samer Abdallah suggested this feature based on |
2549 | 2549 | experience with non-Prolog users using the RDF library.} and the R |
2550 | 2550 | interface for specifying functions or variables that start with an |
2551 | uppercase character. Lexical databases were part of the terms start with | |
2551 | uppercase character. Lexical databases where part of the terms start with | |
2552 | 2552 | an uppercase letter is another category were the readability of the code |
2553 | 2553 | improves using this option. |
2554 | 2554 |
108 | 108 | \begin{description} |
109 | 109 | \termitem{stack_limit}{+Bytes} |
110 | 110 | Sets default stack limit for the new process. See the command line |
111 | option \cmdlineoption{--stack-limit} and the Prolog flag | |
111 | option \cmdlineoption{--stack_limit} and the Prolog flag | |
112 | 112 | \prologflag{stack_limit}. |
113 | 113 | \termitem{goal}{:Callable} |
114 | 114 | Initialization goal for the new executable (see \cmdlineoption{-g}). |
115 | Two values have special meaning: \const{prolog} starts the Prolog | |
116 | toplevel and \const{default} runs halt/0 if there are initialization | |
117 | goals and the prolog/0 toplevel otherwise. | |
115 | 118 | \termitem{toplevel}{:Callable} |
116 | 119 | Top-level goal for the new executable (see \cmdlineoption{-t}). Similar |
117 | 120 | to initialization/2 using \const{main}, the default toplevel is to enter |
2 | 2 | Author: Jan Wielemaker and Matt Lilley |
3 | 3 | E-mail: J.Wielemaker@cs.vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2012-2018, VU University Amsterdam | |
5 | Copyright (c) 2012-2019, VU University Amsterdam | |
6 | 6 | All rights reserved. |
7 | 7 | |
8 | 8 | Redistribution and use in source and binary forms, with or without |
44 | 44 | archive_extract/3, % +Archive, +Dir, +Options |
45 | 45 | |
46 | 46 | archive_entries/2, % +Archive, -Entries |
47 | archive_data_stream/3 % +Archive, -DataStream, +Options | |
47 | archive_data_stream/3, % +Archive, -DataStream, +Options | |
48 | archive_foldl/4 % :Goal, +Archive, +State0, -State | |
48 | 49 | ]). |
49 | 50 | :- use_module(library(error)). |
50 | 51 | :- use_module(library(lists)). |
51 | 52 | :- use_module(library(option)). |
52 | 53 | :- use_module(library(filesex)). |
53 | 54 | |
55 | :- meta_predicate | |
56 | archive_foldl(4, +, +, -). | |
57 | ||
54 | 58 | /** <module> Access several archive formats |
55 | 59 | |
56 | 60 | This library uses _libarchive_ to access a variety of archive formats. |
57 | 61 | The following example lists the entries in an archive: |
58 | 62 | |
59 | == | |
63 | ``` | |
60 | 64 | list_archive(File) :- |
61 | 65 | archive_open(File, Archive, []), |
62 | 66 | repeat, |
66 | 70 | ; !, |
67 | 71 | archive_close(Archive) |
68 | 72 | ). |
69 | == | |
70 | ||
71 | @see http://code.google.com/p/libarchive/ | |
73 | ``` | |
74 | ||
75 | Here is another example which counts the files in the archive and prints | |
76 | file type information. It uses archive_foldl/4, a higher level | |
77 | predicate: | |
78 | ||
79 | ``` | |
80 | print_entry(Path, Handle, Cnt0, Cnt1) :- | |
81 | archive_header_property(Handle, filetype(Type)), | |
82 | format('File ~w is of type ~w~n', [Path, Type]), | |
83 | Cnt1 is Cnt0 + 1. | |
84 | ||
85 | list_archive(File) :- | |
86 | archive_foldl(print_entry, File, 0, FileCount), | |
87 | format('We have ~w files', [FileCount]). | |
88 | ``` | |
89 | ||
90 | @see https://github.com/libarchive/libarchive/ | |
72 | 91 | */ |
73 | 92 | |
74 | 93 | :- use_foreign_library(foreign(archive4pl)). |
550 | 569 | entry_name('.', Name, Name) :- !. |
551 | 570 | entry_name(Base, Name, EntryName) :- |
552 | 571 | directory_file_path(Base, EntryName, Name). |
572 | ||
573 | %! archive_foldl(:Goal, +Archive, +State0, -State). | |
574 | % | |
575 | % Operates like foldl/4 but for the entries in the archive. For each | |
576 | % member of the archive, Goal called as `call(:Goal, +Path, +Handle, | |
577 | % +S0, -S1). Here, `S0` is current state of the _accumulator_ | |
578 | % (starting with State0) and `S1` is the next state of the | |
579 | % accumulator, producing State after the last member of the archive. | |
580 | % | |
581 | % @see archive_header_property/2, archive_open/4. | |
582 | % | |
583 | % @arg Archive File name or stream to be given to archive_open/[3,4]. | |
584 | ||
585 | archive_foldl(Goal, Archive, State0, State) :- | |
586 | setup_call_cleanup( | |
587 | archive_open(Archive, Handle, [close_parent(true)]), | |
588 | archive_foldl_(Goal, Handle, State0, State), | |
589 | archive_close(Handle) | |
590 | ). | |
591 | ||
592 | archive_foldl_(Goal, Handle, State0, State) :- | |
593 | ( archive_next_header(Handle, Path) | |
594 | -> call(Goal, Path, Handle, State0, State1), | |
595 | archive_foldl_(Goal, Handle, State1, State) | |
596 | ; State = State0 | |
597 | ). |
513 | 513 | % a plain `Mode`, which adds new permissions, revokes permissions or |
514 | 514 | % sets the exact permissions. `Mode` itself is an integer, a POSIX |
515 | 515 | % mode name or a list of POSIX mode names. Defines names are `suid`, |
516 | % `sgid`, `svtx` and the all names defined by the regular expression | |
516 | % `sgid`, `svtx` and all names defined by the regular expression | |
517 | 517 | % =|[ugo]*[rwx]*|=. Specifying none of "ugo" is the same as specifying |
518 | 518 | % all of them. For example, to make a file executable for the owner |
519 | 519 | % (user) and group, we can use: |
2450 | 2450 | % |
2451 | 2451 | % True if input represents a valid Cookie option. Officially, all |
2452 | 2452 | % cookie options use the syntax <name>=<value>, except for |
2453 | % =secure=. M$ decided to extend this to include at least | |
2454 | % =httponly= (only the Gods know what it means). | |
2453 | % =Secure= and =HttpOnly=. | |
2455 | 2454 | % |
2456 | 2455 | % @param Option Term of the form Name=Value |
2457 | 2456 | % @bug Incorrectly accepts options without = for M$ compatibility. |
0 | ---+ [jsonsupport] Supporting JSON | |
0 | # Supporting JSON {#jsonsupport} | |
1 | 1 | |
2 | 2 | From http://json.org, " |
3 | 3 | JSON (JavaScript Object Notation) is a lightweight data-interchange |
10 | 10 | many others. These properties make JSON an ideal data-interchange |
11 | 11 | language." |
12 | 12 | |
13 | JSON is interesting to Prolog because using AJAX web technology we can | |
14 | easily created web-enabled user interfaces where we implement the server | |
15 | side using the SWI-Prolog HTTP services provided by this package. | |
16 | The interface consists of three libraries: | |
13 | Although JSON is nowadays used a lot outside the context of web | |
14 | applications, SWI-Prolog's support for JSON started life as part of the | |
15 | HTTP package. SWI-Prolog supports two Prolog representations for JSON | |
16 | terms. The first and oldest map JSON objects to a term | |
17 | json(PropertyList) and use the `@` functor to disambiguate e.g. `null` | |
18 | from the string `"null"`, leading to `@(null)`. As of SWI-Prolog version | |
19 | 7, JSON objects may be represented using _dict_ objects and JSON strings | |
20 | using Prolog strings. Predicates following this convention are suffixed | |
21 | with ``_dict``, e.g. json_read_dict/2. For example, given the JSON document | |
22 | ||
23 | { "name": "Bob", "children": ["Mary", "John"], "age":42, "married": true } | |
24 | ||
25 | we get either (using json_read/2): | |
26 | ||
27 | json([name='Bob', children=['Mary', 'John'], age=42, married= @(true)]). | |
28 | ||
29 | or (using json_read_dict/2): | |
30 | ||
31 | _{age:42, children:["Mary", "John"], married:true, name:"Bob"} | |
32 | ||
33 | ||
34 | The SWI-Prolog JSON interface consists of three libraries: | |
17 | 35 | |
18 | 36 | * library(http/json) provides support for the core JSON object |
19 | serialization. | |
37 | serialization and parsing. | |
20 | 38 | * library(http/json_convert) converts between the primary |
21 | 39 | representation of JSON terms in Prolog and more application |
22 | 40 | oriented Prolog terms. E.g. point(X,Y) vs. object([x=X,y=Y]). |
23 | 41 | * library(http/http_json) hooks the conversion libraries into |
24 | 42 | the HTTP client and server libraries. |
25 | 43 | |
26 | [[json.pl]] | |
27 | [[json_convert.pl]] | |
28 | [[http_json.pl]] | |
44 | [[library(http/json)]] | |
45 | [[library(http/json_convert)]] | |
46 | [[library(http/http_json)]] | |
29 | 47 |
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-2019, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | CWI, Amsterdam |
8 | 8 | All rights reserved. |
894 | 894 | % Default the atom `true`. |
895 | 895 | % * false(+FalseTerm) |
896 | 896 | % Default the atom `false` |
897 | % * end_of_file(+ErrorOrTerm) | |
898 | % Action on reading end-of-file. See json_read/3 for details. | |
897 | 899 | % * value_string_as(+Type) |
898 | 900 | % Prolog type used for strings used as value. Default |
899 | 901 | % is `string`. The alternative is `atom`, producing a |
150 | 150 | |
151 | 151 | swipl_examples(FILES ${EXPL} SUBDIR prolog) |
152 | 152 | swipl_examples(DIRECTORIES ${EXJAVA} SUBDIR java) |
153 | swipl_examples(FILES examples/java/env.sh SUBDIR java) | |
153 | 154 | |
154 | 155 | ################ |
155 | 156 | # Documentation |
382 | 382 | JPL 7.4.0-alpha |
383 | 383 | ``` |
384 | 384 | |
385 | ## Gotchas | |
386 | ||
387 | ### Arg indexing | |
385 | ## Gotchas | |
386 | ||
387 | ### Variables are named | |
388 | ||
389 | Instances of `org.jpl7.Variable` have names, and bindings are retrieved by name, e.g. | |
390 | ||
391 | ``` | |
392 | Map m = org.jpl7.Query.oneSolution("statistics(heap, X)"); | |
393 | long heapsize = m.get("X"); | |
394 | ``` | |
395 | ||
396 | ### Argument numbering | |
388 | 397 | |
389 | 398 | The `Term[]` args of a `Compound` are indexed (like all Java arrays) from zero, whereas in Prolog the args of a structure are conventionally numbered from one. |
390 | 399 |
0 | 0 | # Prolog API - Overview |
1 | 1 | |
2 | 2 | The Prolog API comprises Prolog library predicates which support: |
3 | * creating instances (objects) of Java classes (built-in and user-defined); | |
4 | * calling methods of Java objects (and static methods of classes), perhaps returning values or object references; and | |
5 | * getting and setting the values of fields of Java objects and classes. | |
3 | * creating instances (objects) of Java classes (built-in and user-defined); | |
4 | * calling methods of Java objects (and static methods of classes), perhaps returning values or object references; and | |
5 | * getting and setting the values of fields of Java objects and classes. | |
6 | 6 | |
7 | 7 | |
8 | 8 | ## Introduction |
325 | 325 | |
326 | 326 | Unfortunately it is far from trivial to support the Java naming in JPL. Thanks go to Timo Baumann and Sebastian Godelet for their input on this issue. |
327 | 327 | |
328 | ### Instantiating a non-static member class | |
329 | ||
330 | If you need to create an instance of a non-static member class, you must explicitly pass (a reference to) an instance of its parent class as an additional (first) argument of any of its constructors. Java source syntax hides this, but reflection shows that every constructor (implicit or explicit) has this extra argument. | |
331 | ||
332 | ```java | |
333 | public class Parent { | |
334 | public class Child { | |
335 | } | |
336 | } | |
337 | ``` | |
338 | ||
339 | ```prolog | |
340 | jpl_new('Parent', [], P), | |
341 | jpl_new('Parent$Child', [P], C). | |
342 | ``` | |
343 | ||
328 | 344 | ### Enums are static nested classes |
329 | 345 | |
330 | 346 | Given |
6 | 6 | Create a new Java object. |
7 | 7 | |
8 | 8 | *X* can be: |
9 | * an atomic classname, e.g. `'java.lang.String'` (or `'Ljava.lang.String;'`) | |
9 | * an atomic classname, e.g. `'java.util.Date'` | |
10 | 10 | * a suitable type, i.e. any `class(_,_)`, `array(_)` or primitive type (e.g. `byte`) but not `null` or `void |
11 | * an atomic descriptor, e.g. `'[I'` | |
11 | * an atomic descriptor, e.g. `'[I'` or `'[Ljava.lang.String;'` | |
12 | 12 | * a class object, i.e. an object whose type is `class([java,lang],['Class'])` |
13 | 13 | |
14 | 14 | *Args* is typically a list of datums (values or jrefs) to be passed to the appropriate constructor. |
389 | 389 | <li class="level3 navJavaApiOverview"><div onclick="scrollToId('debugging')">Debugging</div></li> |
390 | 390 | <li class="level3 navJavaApiOverview"><div onclick="scrollToId('version-information')">Version information</div></li> |
391 | 391 | <li class="level3 navJavaApiOverview"><div onclick="scrollToId('gotchas')">Gotchas</div></li> |
392 | <li class="level4 navJavaApiOverview"><div onclick="scrollToId('arg-indexing')">Arg indexing</div></li> | |
392 | <li class="level4 navJavaApiOverview"><div onclick="scrollToId('variables-are-named')">Variables are named</div></li> | |
393 | <li class="level4 navJavaApiOverview"><div onclick="scrollToId('argument-numbering')">Argument numbering</div></li> | |
393 | 394 | <li class="level4 navJavaApiOverview"><div onclick="scrollToId('representing-null')">Representing @(null)</div></li> |
394 | 395 | <li class="level4 navJavaApiOverview"><div onclick="scrollToId('all-solutions-of-a-query-with-no-solutions')">All solutions of a Query with no solutions</div></li> |
395 | 396 | <!-- |
57 | 57 | # Setup the environment |
58 | 58 | ################################################################ |
59 | 59 | |
60 | eval `$PL -dump-runtime-variables` | |
60 | eval `$PL --dump-runtime-variables` | |
61 | 61 | |
62 | 62 | PLLIBDIR="$PLBASE/lib/$PLARCH" |
63 | 63 | if [ -z "$JPLJAR" ]; then |
64 | JPLJAR="$PLBASE/lib/jpl.jar" | |
64 | if [ -f "$PLBASE/lib/jpl.jar" ]; then | |
65 | JPLJAR="$PLBASE/lib/jpl.jar" | |
66 | elif [ -f "$PLBASE/../packages/jpl/src/java/jpl.jar" ]; then | |
67 | JPLJAR="$PLBASE/../packages/jpl/src/java/jpl.jar" | |
68 | else | |
69 | echo "ERROR: Cannot find jpl.jar (PLBASE=$PLBASE)" | |
70 | exit 1 | |
71 | fi | |
72 | fi | |
73 | ||
74 | JPL_LIBRARY_PATH="$PLLIBDIR" | |
75 | if [ ! -f "$PLLIBDIR/libjpl.$PLSOEXT" ]; then | |
76 | if [ -f "$PLBASE/../packages/jpl/libjpl.$PLSOEXT" ]; then | |
77 | JPL_LIBRARY_PATH="$PLLIBDIR:$PLBASE/../packages/jpl" | |
78 | else | |
79 | echo "ERROR: Cannot find libjpl.$PLSOEXT" | |
80 | exit 1 | |
81 | fi | |
65 | 82 | fi |
66 | 83 | |
67 | 84 | if [ -z "$LD_LIBRARY_PATH" ]; then |
68 | LD_LIBRARY_PATH="$PLLIBDIR"; | |
85 | LD_LIBRARY_PATH="$JPL_LIBRARY_PATH"; | |
69 | 86 | else |
70 | LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PLLIBDIR" | |
87 | LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$JPL_LIBRARY_PATH" | |
71 | 88 | fi |
72 | 89 | |
73 | 90 | if [ -z "$CLASSPATH" ]; then |
76 | 93 | CLASSPATH=".:$JPLJAR:$CLASSPATH" |
77 | 94 | fi |
78 | 95 | |
96 | echo CLASSPATH=$CLASSPATH | |
97 | echo LD_LIBRARY_PATH=$LD_LIBRARY_PATH | |
79 | 98 | export LD_LIBRARY_PATH CLASSPATH |
80 | 99 | |
81 | 100 | ################################################################ |
113 | 132 | echo "JPL demo: $1" |
114 | 133 | echo "" |
115 | 134 | |
116 | java -Djava.library.path=$PLLIBDIR $* | |
135 | java -Djava.library.path=$JPL_LIBRARY_PATH $* | |
117 | 136 | fi |
118 | 137 | } |
119 | 138 |
2585 | 2585 | output_result(Format, Event) :- |
2586 | 2586 | arg(1, Event, Pengine), |
2587 | 2587 | thread_self(Thread), |
2588 | cors_enable, % contingent on http:cors setting | |
2589 | disable_client_cache, | |
2588 | 2590 | setup_call_cleanup( |
2589 | 2591 | asserta(pengine_replying(Pengine, Thread), Ref), |
2590 | 2592 | catch(output_result(Format, Event, _{}), |
2592 | 2594 | true), |
2593 | 2595 | erase(Ref)). |
2594 | 2596 | |
2597 | output_result(Lang, Event, Dict) :- | |
2598 | write_result(Lang, Event, Dict), | |
2599 | !. | |
2595 | 2600 | output_result(prolog, Event, _) :- |
2596 | 2601 | !, |
2597 | 2602 | format('Content-type: text/x-prolog; charset=UTF-8~n~n'), |
2603 | 2608 | portray_goal(portray_blob), |
2604 | 2609 | nl(true) |
2605 | 2610 | ]). |
2606 | output_result(Lang, Event, Dict) :- | |
2607 | write_result(Lang, Event, Dict), | |
2608 | !. | |
2609 | 2611 | output_result(Lang, Event, _) :- |
2610 | 2612 | json_lang(Lang), |
2611 | 2613 | !, |
2612 | 2614 | ( event_term_to_json_data(Event, JSON, Lang) |
2613 | -> cors_enable, | |
2614 | disable_client_cache, | |
2615 | reply_json(JSON) | |
2615 | -> reply_json(JSON) | |
2616 | 2616 | ; assertion(event_term_to_json_data(Event, _, Lang)) |
2617 | 2617 | ). |
2618 | 2618 | output_result(Lang, _Event, _) :- % FIXME: allow for non-JSON format |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2014-2018, VU University Amsterdam | |
5 | Copyright (c) 2014-2019, VU University Amsterdam | |
6 | 6 | CWI, Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
75 | 75 | :- if(exists_source(library(prolog_stream))). |
76 | 76 | :- use_module(library(prolog_stream)). |
77 | 77 | :- endif. |
78 | ||
78 | 79 | :- html_meta send_html(html). |
80 | :- public send_html/1. | |
79 | 81 | |
80 | 82 | :- meta_predicate |
81 | 83 | pengine_format(+,:). |
92 | 92 | if ( from[k] !== undefined ) |
93 | 93 | to[k] = from[k]; |
94 | 94 | } |
95 | } | |
96 | ||
97 | // initialize network support in browser | |
98 | if (typeof Pengine.network === "undefined") { | |
99 | Pengine.network = $; // assume jQuery initialized by now | |
100 | $(window).on("beforeunload", function() { | |
101 | Pengine.destroy_all(); | |
102 | }); | |
95 | 103 | } |
96 | 104 | |
97 | 105 | // create instance |
677 | 685 | var najax = require('najax'); |
678 | 686 | Pengine.network = najax; |
679 | 687 | Pengine.network.ajax = najax; |
680 | } else { | |
681 | Pengine.network = $; | |
682 | // Browser | |
683 | $(window).on("beforeunload", function() { | |
684 | Pengine.destroy_all(); | |
685 | }); | |
686 | 688 | } |
365 | 365 | module_info(File, ModuleOptions, Options), |
366 | 366 | file_info(Objs0, Objs1, FileOptions, ModuleOptions), |
367 | 367 | doc_hide_private(Objs1, ObjectsSelf, ModuleOptions), |
368 | include_reexported(ObjectsSelf, Objects, File, FileOptions). | |
368 | include_reexported(ObjectsSelf, Objects1, File, FileOptions), | |
369 | remove_doc_duplicates(Objects1, Objects, []). | |
370 | ||
371 | remove_doc_duplicates([], [], _). | |
372 | remove_doc_duplicates([H|T0], [H|T], Seen) :- | |
373 | H = doc(_, _, Comment), | |
374 | \+ memberchk(Comment, Seen), | |
375 | !, | |
376 | remove_doc_duplicates(T0, T, [Comment|Seen]). | |
377 | remove_doc_duplicates([_|T0], T, Seen) :- | |
378 | remove_doc_duplicates(T0, T, Seen). | |
369 | 379 | |
370 | 380 | include_reexported(SelfObjects, Objects, File, Options) :- |
371 | 381 | option(include_reexported(true), Options), |
462 | 462 | % Tranform the Name/Arity, etc strings as received from the HTTP |
463 | 463 | % into a term. Must return unique results. |
464 | 464 | |
465 | object_spec(Spec, Spec). | |
465 | object_spec(Spec, Spec) :- | |
466 | compound(Spec), | |
467 | !. | |
466 | 468 | object_spec(Atom, Spec) :- |
467 | 469 | catch(atom_to_term(Atom, Spec, _), _, fail), |
468 | 470 | !, |
920 | 920 | char_type(Token, punct). |
921 | 921 | |
922 | 922 | |
923 | identifier_match_quality(Identifier, Identifier, 1) :- | |
924 | !. | |
925 | identifier_match_quality(For, Identifier, Q) :- | |
926 | dwim_match(For, Identifier, _), | |
927 | !, | |
928 | Q = 0.8. | |
923 | 929 | identifier_match_quality(For, Identifier, Q) :- |
924 | 930 | identifier_parts(Identifier, Parts), |
925 | 931 | Parts \== [], |
1356 | 1356 | ['.'], file_extension(Extension), |
1357 | 1357 | !, |
1358 | 1358 | { atomic_list_concat([S1|List], '/', FileBase) }. |
1359 | file_name(FileBase, Extension) --> | |
1360 | [w(Alias), '('], | |
1361 | { once(user:file_search_path(Alias, _)) }, | |
1362 | segment(S1), | |
1363 | segments(List), | |
1364 | [')'], | |
1365 | !, | |
1366 | { atomic_list_concat([S1|List], '/', Base), | |
1367 | Spec =.. [Alias,Base], | |
1368 | absolute_file_name(Spec, Path, | |
1369 | [ access(read), | |
1370 | extensions([pl]), | |
1371 | file_type(prolog) | |
1372 | ]), | |
1373 | file_name_extension(FileBase, Extension, Path) | |
1374 | }. | |
1375 | ||
1359 | 1376 | |
1360 | 1377 | segment(..) --> |
1361 | 1378 | ['.','.'], |
4 | 4 | origin of the triple. |
5 | 5 | |
6 | 6 | The actual storage is provided by the _|foreign language (C)|_ module. |
7 | Using a dedicated C-based implementation we can reduced memory usage and | |
7 | Using a dedicated C-based implementation we can reduce memory usage and | |
8 | 8 | improve indexing capabilities, for example by providing a dedicated |
9 | 9 | index to support entailment over =|rdfs:subPropertyOf|=. Currently the |
10 | 10 | following indexes are provided (S=subject, P=predicate, O=object, |
12 | 12 | |
13 | 13 | * S, P, O, SP, PO, SPO, G, SG, PG |
14 | 14 | |
15 | * Predicates connect by *|rdfs:subPropertyOf|* are combined | |
15 | * Predicates connected by *|rdfs:subPropertyOf|* are combined | |
16 | 16 | in a _|predicate cloud|_. The system causes multiple |
17 | 17 | predicates in the cloud to share the same hash. The cloud |
18 | 18 | maintains a 2-dimensional array that expresses the |
19 | closure of all rdfs:subPropertyOf relations. This | |
19 | closure of all =|rdfs:subPropertyOf|= relations. This | |
20 | 20 | index supports rdf_has/3 to query a property and all its |
21 | 21 | children efficiently. |
22 | 22 | |
148 | 148 | |
149 | 149 | ## Literal matching and indexing {#semweb-literals} |
150 | 150 | |
151 | Literal values are ordered and indexed using a _|skip list|_ The aim of | |
151 | Literal values are ordered and indexed using a _|skip list|_. The aim of | |
152 | 152 | this index is threefold. |
153 | 153 | |
154 | 154 | * Unlike hash-tables, binary trees allow for efficient |
174 | 174 | Currently the total order of literals is first based on the type of |
175 | 175 | literal using the ordering _|numeric < string < term|_ Numeric values |
176 | 176 | (integer and float) are ordered by value, integers preceed floats if |
177 | they represent the same value. strings are sorted alphabetically after | |
177 | they represent the same value. Strings are sorted alphabetically after | |
178 | 178 | case-mapping and diacritic removal as described above. If they match |
179 | 179 | equal, uppercase preceeds lowercase and diacritics are ordered on their |
180 | 180 | unicode value. If they still compare equal literals without any |
192 | 192 | The predicates below form an experimental interface to provide more |
193 | 193 | reasoning inside the kernel of the rdb_db engine. Note that =symetric=, |
194 | 194 | =inverse_of= and =transitive= are not yet supported by the rest of the |
195 | engine. Alo note that there is no relation to defined RDF properties. | |
195 | engine. Also note that there is no relation to defined RDF properties. | |
196 | 196 | Properties that have no triples are not reported by this predicate, |
197 | 197 | while predicates that are involved in triples do not need to be defined |
198 | 198 | as an instance of rdf:Property. |
423 | 423 | % |
424 | 424 | % If both S and O are given, these predicates are `semidet`. The |
425 | 425 | % number of steps D is minimal because the implementation uses |
426 | % _breath first_ search. | |
426 | % _breadth first_ search. | |
427 | 427 | |
428 | 428 | rdf_reachable(S,P,O) :- |
429 | 429 | pre_object(O,O0), |
1484 | 1484 | |
1485 | 1485 | %! rdf_term(?Term) is nondet. |
1486 | 1486 | % |
1487 | % True if Term appears in the RDF database. Term is either an iri, | |
1487 | % True if Term appears in the RDF database. Term is either an IRI, | |
1488 | 1488 | % literal or blank node and may appear in any position of any |
1489 | 1489 | % triple. If Term is ground, it is pre-processed as the object |
1490 | 1490 | % argument of rdf_assert/3 and the predicate is _semidet_. |
1596 | 1596 | |
1597 | 1597 | %! rdf_object(?O) is nondet. |
1598 | 1598 | % |
1599 | % True when O is a currently known object, i.e. it appeasr in the | |
1599 | % True when O is a currently known object, i.e. it appears in the | |
1600 | 1600 | % object position of some visible triple. If Term is ground, it is |
1601 | 1601 | % pre-processed as the object argument of rdf_assert/3 and the |
1602 | 1602 | % predicate is _semidet_. |
1754 | 1754 | % |
1755 | 1755 | % Success of this goal does not imply that the name is |
1756 | 1756 | % well-formed or that it is present in the database (see |
1757 | % rdf_name/1) for that). | |
1757 | % rdf_name/1 for that). | |
1758 | 1758 | |
1759 | 1759 | rdf_is_name(T) :- rdf_is_iri(T), !. |
1760 | 1760 | rdf_is_name(T) :- rdf_is_literal(T). |
1766 | 1766 | % |
1767 | 1767 | % Success of this goal does not imply that the object term in |
1768 | 1768 | % well-formed or that it is present in the database (see |
1769 | % rdf_object/1) for that). | |
1769 | % rdf_object/1 for that). | |
1770 | 1770 | % |
1771 | 1771 | % Since any RDF term can appear in the object position, this is |
1772 | 1772 | % equaivalent to rdf_is_term/1. |
1780 | 1780 | % True if Term can appear in the predicate position of a triple. |
1781 | 1781 | % |
1782 | 1782 | % Success of this goal does not imply that the predicate term is |
1783 | % present in the database (see rdf_predicate/1) for that). | |
1783 | % present in the database (see rdf_predicate/1 for that). | |
1784 | 1784 | % |
1785 | 1785 | % Since only IRIs can appear in the predicate position, this is |
1786 | 1786 | % equivalent to rdf_is_iri/1. |
1795 | 1795 | % Only blank nodes and IRIs can appear in the subject position. |
1796 | 1796 | % |
1797 | 1797 | % Success of this goal does not imply that the subject term is |
1798 | % present in the database (see rdf_subject/1) for that). | |
1798 | % present in the database (see rdf_subject/1 for that). | |
1799 | 1799 | % |
1800 | 1800 | % Since blank nodes are represented by atoms that start with |
1801 | 1801 | % `_:` and an IRIs are atoms as well, this is equivalent to |
1809 | 1809 | % either an IRI, a blank node or an RDF literal. |
1810 | 1810 | % |
1811 | 1811 | % Success of this goal does not imply that the RDF term is |
1812 | % present in the database (see rdf_term/1) for that). | |
1812 | % present in the database (see rdf_term/1 for that). | |
1813 | 1813 | |
1814 | 1814 | rdf_is_term(N) :- rdf_is_subject(N), !. |
1815 | 1815 | rdf_is_term(N) :- rdf_is_literal(N). |
286 | 286 | |
287 | 287 | %! rdf_equal(?Resource1, ?Resource2) |
288 | 288 | % |
289 | % Simple equality test to exploit goal-expansion | |
289 | % Simple equality test to exploit goal-expansion. | |
290 | 290 | |
291 | 291 | rdf_equal(Resource, Resource). |
292 | 292 | |
306 | 306 | % True if Lang matches Pattern. This implements XML language |
307 | 307 | % matching conform RFC 4647. Both Lang and Pattern are |
308 | 308 | % dash-separated strings of identifiers or (for Pattern) the |
309 | % wildcart *. Identifiers are matched case-insensitive and a * | |
309 | % wildcard *. Identifiers are matched case-insensitive and a * | |
310 | 310 | % matches any number of identifiers. A short pattern is the same |
311 | 311 | % as *. |
312 | 312 | |
375 | 375 | % literals. |
376 | 376 | % |
377 | 377 | % * ge(+Literal) |
378 | % Match any literal that is equal or larger then Literal in the | |
378 | % Match any literal that is equal or larger than Literal in the | |
379 | 379 | % ordered set of literals. |
380 | 380 | % |
381 | 381 | % * gt(+Literal) |
382 | % Match any literal that is larger then Literal in the ordered set | |
382 | % Match any literal that is larger than Literal in the ordered set | |
383 | 383 | % of literals. |
384 | 384 | % |
385 | 385 | % * eq(+Literal) |
387 | 387 | % of literals. |
388 | 388 | % |
389 | 389 | % * le(+Literal) |
390 | % Match any literal that is equal or smaller then Literal in the | |
390 | % Match any literal that is equal or smaller than Literal in the | |
391 | 391 | % ordered set of literals. |
392 | 392 | % |
393 | 393 | % * lt(+Literal) |
394 | % Match any literal that is smaller then Literal in the ordered set | |
394 | % Match any literal that is smaller than Literal in the ordered set | |
395 | 395 | % of literals. |
396 | 396 | % |
397 | 397 | % * between(+Literal1, +Literal2) |
442 | 442 | % repecting the symetric(true) or inverse_of(P2) properties. |
443 | 443 | % |
444 | 444 | % If used with either Subject or Object unbound, it first returns |
445 | % the origin, followed by the reachable nodes in breath-first | |
445 | % the origin, followed by the reachable nodes in breadth-first | |
446 | 446 | % search-order. The implementation internally looks one solution |
447 | 447 | % ahead and succeeds deterministically on the last solution. This |
448 | 448 | % predicate never generates the same node twice and is robust |
835 | 835 | % Obtain statistics on the RDF database. Defined statistics are: |
836 | 836 | % |
837 | 837 | % * graphs(-Count) |
838 | % Number of named graphs | |
838 | % Number of named graphs. | |
839 | 839 | % |
840 | 840 | % * triples(-Count) |
841 | 841 | % Total number of triples in the database. This is the number |
986 | 986 | % * rdf_object_branch_factor(-Float) |
987 | 987 | % Unify Float with the average number of triples associated with |
988 | 988 | % each unique value for the object-side of this relation. In |
989 | % addition to the comments with the subject_branch_factor | |
989 | % addition to the comments with the =rdf_subject_branch_factor= | |
990 | 990 | % property, uniqueness of the object value is computed from the |
991 | 991 | % hash key rather than the actual values. |
992 | 992 | % |
1360 | 1360 | % Named graph in which to load the data. It is *not* allowed |
1361 | 1361 | % to load two sources into the same named graph. If Graph is |
1362 | 1362 | % unbound, it is unified to the graph into which the data is |
1363 | % loaded. The default graph is a =file://= URL when loading | |
1363 | % loaded. The default graph is a =|file://|= URL when loading | |
1364 | 1364 | % a file or, if the specification is a URL, its normalized |
1365 | 1365 | % version without the optional _|#fragment|_. |
1366 | 1366 | % |
1997 | 1997 | % The graph is loaded from the Source (a URL) |
1998 | 1998 | % * source_last_modified(?Time) |
1999 | 1999 | % Time is the last-modified timestamp of Source at the moment |
2000 | % that the graph was loaded from Source. | |
2000 | % the graph was loaded from Source. | |
2001 | 2001 | % * triples(Count) |
2002 | 2002 | % True when Count is the number of triples in Graph. |
2003 | 2003 | % |
2103 | 2103 | % Save only triples associated to the given named Graph. |
2104 | 2104 | % |
2105 | 2105 | % * anon(Bool) |
2106 | % If false (default true) do not save blank nodes that do | |
2106 | % If =false= (default =true=) do not save blank nodes that do | |
2107 | 2107 | % not appear (indirectly) as object of a named resource. |
2108 | 2108 | % |
2109 | 2109 | % * base_uri(URI) |
2110 | 2110 | % BaseURI used. If present, all URIs that can be |
2111 | 2111 | % represented relative to this base are written using |
2112 | % their shorthand. See also =write_xml_base= option | |
2112 | % their shorthand. See also =write_xml_base= option. | |
2113 | 2113 | % |
2114 | 2114 | % * convert_typed_literal(:Convertor) |
2115 | 2115 | % Call Convertor(-Type, -Content, +RDFObject), providing |
2117 | 2117 | % the RDF parser. |
2118 | 2118 | % |
2119 | 2119 | % * document_language(+Lang) |
2120 | % Initial xml:lang saved with rdf:RDF element | |
2120 | % Initial =|xml:lang|= saved with rdf:RDF element. | |
2121 | 2121 | % |
2122 | 2122 | % * encoding(Encoding) |
2123 | % Encoding for the output. Either utf8 or iso_latin_1 | |
2123 | % Encoding for the output. Either utf8 or iso_latin_1. | |
2124 | 2124 | % |
2125 | 2125 | % * inline(+Bool) |
2126 | 2126 | % If =true= (default =false=), inline resources when |
2128 | 2128 | % are handled this way. |
2129 | 2129 | % |
2130 | 2130 | % * namespaces(+List) |
2131 | % Explicitely specify saved namespace declarations. See | |
2131 | % Explicitly specify saved namespace declarations. See | |
2132 | 2132 | % rdf_save_header/2 option namespaces for details. |
2133 | 2133 | % |
2134 | 2134 | % * sorted(+Boolean) |
179 | 179 | % Register Prefix as an abbreviation for URI. Options: |
180 | 180 | % |
181 | 181 | % * force(Boolean) |
182 | % If =true=, Replace existing namespace alias. Please note | |
182 | % If =true=, replace existing namespace alias. Please note | |
183 | 183 | % that replacing a namespace is dangerous as namespaces |
184 | 184 | % affect preprocessing. Make sure all code that depends on |
185 | 185 | % a namespace is compiled after changing the registration. |
266 | 266 | |
267 | 267 | %! rdf_current_ns(:Prefix, ?URI) is nondet. |
268 | 268 | % |
269 | % @deprecated. Use rdf_current_prefix/2. | |
269 | % @deprecated Use rdf_current_prefix/2. | |
270 | 270 | |
271 | 271 | rdf_current_ns(Prefix, URI) :- |
272 | 272 | rdf_current_prefix(Prefix, URI). |
276 | 276 | % |
277 | 277 | % Register an RDF prefix. |
278 | 278 | % |
279 | % @deprecated. Use rdf_register_prefix/2 or rdf_register_prefix/3. | |
279 | % @deprecated Use rdf_register_prefix/2 or rdf_register_prefix/3. | |
280 | 280 | |
281 | 281 | rdf_register_ns(Prefix, URI) :- |
282 | 282 | rdf_register_prefix(Prefix, URI). |
35 | 35 | persistent storage. This package is the core of a ready-to-run platform |
36 | 36 | for developing Semantic Web applications named |
37 | 37 | \href{http://cliopatria.swi-prolog.org}{ClioPatria}, which is distributed |
38 | seperately. The SWI-Prolog RDF store is amoung the most memory efficient | |
38 | seperately. The SWI-Prolog RDF store is among the most memory efficient | |
39 | 39 | main-memory stores for |
40 | 40 | RDF\footnote{\url{http://cliopatria.swi-prolog.org/help/source/doc/home/vnc/prolog/src/ClioPatria/web/help/memusage.txt}} |
41 | 41 | |
42 | 42 | Version~3 of the RDF library enhances concurrent use of the library by |
43 | 43 | allowing for lock-free reading and writing using short-held locks. It |
44 | 44 | provides Prolog compatible \jargon{logical update view} on the triple |
45 | store and isolation using \jargon{transactions} and jargon{snapshots}. | |
45 | store and isolation using \jargon{transactions} and \jargon{snapshots}. | |
46 | 46 | This version of the library provides near real-time modification and |
47 | 47 | querying of RDF graphs, making it particularly interesting for handling |
48 | 48 | streaming RDF and graph manipulation tasks. |
4599 | 4599 | rval = TRUE; |
4600 | 4600 | break; |
4601 | 4601 | case S_CMT: |
4602 | case S_CMT1: | |
4603 | 4602 | case S_CMTE0: |
4604 | 4603 | case S_CMTE1: |
4605 | 4604 | case S_DECLCMT0: |
5276 | 5275 | } |
5277 | 5276 | case S_CMTO: /* Seen <!- */ |
5278 | 5277 | { if ( f[CF_CMT] == chr ) /* - */ |
5279 | { p->state = S_CMT1; | |
5278 | { p->state = S_CMT; | |
5280 | 5279 | return TRUE; |
5281 | 5280 | } else |
5282 | 5281 | { add_cdata(p, f[CF_MDO1]); |
5286 | 5285 | p->state = S_PCDATA; |
5287 | 5286 | return TRUE; |
5288 | 5287 | } |
5289 | } | |
5290 | case S_CMT1: /* <!-- */ | |
5291 | { p->state = S_CMT; | |
5292 | return TRUE; | |
5293 | 5288 | } |
5294 | 5289 | case S_CMT: |
5295 | 5290 | { if ( f[CF_CMT] == chr ) |
108 | 108 | S_DECLCMT, /* Seen <...-- */ |
109 | 109 | S_DECLCMTE0, /* Seen <...--..- */ |
110 | 110 | S_CMTO, /* Seen <!- */ |
111 | S_CMT1, /* Seen <!-- */ | |
112 | 111 | S_CMT, /* Seen <!--X... */ |
113 | 112 | S_CMTE0, /* Seem <!--...- */ |
114 | 113 | S_CMTE1, /* Seem <!--...-- */ |
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-2016, University of Amsterdam | |
5 | Copyright (c) 2009-2019, 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 |
124 | 125 | % Evaluate to the content of the element (a list) |
125 | 126 | % $ =text= : |
126 | 127 | % Evaluates to all text from the sub-tree as an atom |
128 | % $ `text(As)` : | |
129 | % Evaluates to all text from the sub-tree according to | |
130 | % `As`, which is either `atom` or `string`. | |
127 | 131 | % $ =normalize_space= : |
128 | 132 | % As =text=, but uses normalize_space/2 to normalise |
129 | 133 | % white-space in the output |
433 | 437 | element_content(Element, Value). |
434 | 438 | xpath_function(text, DOM, Text) :- % text |
435 | 439 | !, |
436 | text_of_dom(DOM, Text). | |
440 | text_of_dom(DOM, atom, Text). | |
441 | xpath_function(text(As), DOM, Text) :- % text(As) | |
442 | !, | |
443 | text_of_dom(DOM, As, Text). | |
437 | 444 | xpath_function(normalize_space, DOM, Text) :- % normalize_space |
438 | 445 | !, |
439 | text_of_dom(DOM, Text0), | |
446 | text_of_dom(DOM, string, Text0), | |
440 | 447 | normalize_space(atom(Text), Text0). |
441 | 448 | xpath_function(number, DOM, Number) :- % number |
442 | 449 | !, |
443 | text_of_dom(DOM, Text0), | |
450 | text_of_dom(DOM, string, Text0), | |
444 | 451 | normalize_space(string(Text), Text0), |
445 | 452 | catch(xsd_number_string(Number, Text), _, fail). |
446 | 453 | xpath_function(@Name, element(_, Attrs, _), Value) :- % @Name |
458 | 465 | xpath_function(self). |
459 | 466 | xpath_function(content). |
460 | 467 | xpath_function(text). |
468 | xpath_function(text(_)). | |
461 | 469 | xpath_function(normalize_space). |
462 | 470 | xpath_function(number). |
463 | 471 | xpath_function(@_). |
553 | 561 | val_or_function(Value, _, Value). |
554 | 562 | |
555 | 563 | |
556 | %! text_of_dom(+DOM, -Text:atom) is det. | |
564 | %! text_of_dom(+DOM, +As, -Text:atom) is det. | |
557 | 565 | % |
558 | 566 | % Text is the joined textual content of DOM. |
559 | 567 | |
560 | text_of_dom(DOM, Text) :- | |
568 | text_of_dom(DOM, As, Text) :- | |
561 | 569 | phrase(text_of(DOM), Tokens), |
562 | atomic_list_concat(Tokens, Text). | |
570 | ( As == atom | |
571 | -> atomic_list_concat(Tokens, Text) | |
572 | ; As == string | |
573 | -> atomics_to_string(Tokens, Text) | |
574 | ; must_be(oneof([atom,string]), As) | |
575 | ). | |
563 | 576 | |
564 | 577 | text_of(element(_,_,Content)) --> |
565 | 578 | text_of_list(Content). |
581 | 594 | !, |
582 | 595 | text_of_list(Content). |
583 | 596 | text_of_1(Data) --> |
584 | { assertion(atom(Data)) }, | |
597 | { assertion(atom_or_string(Data)) }, | |
585 | 598 | [Data]. |
599 | ||
600 | atom_or_string(Data) :- | |
601 | ( atom(Data) | |
602 | -> true | |
603 | ; string(Data) | |
604 | ). |
12 | 12 | |
13 | 13 | if(Qt5Widgets_FOUND) |
14 | 14 | |
15 | set(PLWIN_RESOURCES | |
16 | swipl-win.qrc) | |
17 | ||
18 | qt5_add_resources(SWIPL_RES_SOURCES ${PLWIN_RESOURCES}) | |
19 | ||
15 | 20 | set(PLWIN_SRC main.cpp SwiPrologEngine.cpp Swipl_IO.cpp Preferences.cpp |
16 | 21 | pqMainWindow.cpp pqConsole.cpp FlushOutputEvents.cpp ConsoleEdit.cpp |
17 | Completion.cpp swipl_win.cpp ParenMatching.cpp) | |
18 | ||
19 | set(PLWIN_MOC | |
20 | qrc_swipl-win.cpp | |
21 | moc_SwiPrologEngine.cpp moc_Swipl_IO.cpp moc_Preferences.cpp | |
22 | moc_pqMainWindow.cpp moc_ConsoleEdit.cpp moc_swipl_win.cpp | |
23 | moc_ParenMatching.cpp) | |
22 | Completion.cpp swipl_win.cpp ParenMatching.cpp ${SWIPL_RES_SOURCES}) | |
24 | 23 | |
25 | 24 | set(QT_DEFINES) |
25 | ||
26 | if(MULTI_THREADED) | |
27 | list(APPEND QT_DEFINES -D_REENTRANT) | |
28 | endif() | |
26 | 29 | |
27 | 30 | # provide appropriate linking mode for |
28 | 31 | # static compilation of pqConsole source files |
707 | 707 | setReadOnly(false); |
708 | 708 | viewport()->setCursor(Qt::IBeamCursor); |
709 | 709 | } |
710 | ||
711 | if (pmatched.size()) { | |
712 | pmatched.format_both(c); | |
713 | pmatched = ParenMatching::range(); | |
714 | } | |
715 | ||
716 | ParenMatching pm(c); | |
717 | if (pm) | |
718 | (pmatched = pm.positions).format_both(c, pmatched.bold()); | |
710 | 719 | } |
711 | 720 | |
712 | 721 | /** check if line content is appropriate, then highlight or open editor on it */ |
49 | 49 | |
50 | 50 | #include "SwiPrologEngine.h" |
51 | 51 | #include "Completion.h" |
52 | #include "ParenMatching.h" | |
52 | 53 | |
53 | 54 | #include <QElapsedTimer> |
54 | 55 | |
243 | 244 | /** relax selection check requirement */ |
244 | 245 | QElapsedTimer sel_check_timing; |
245 | 246 | |
247 | protected: | |
248 | ||
249 | /** keep last matched pair */ | |
250 | ParenMatching::range pmatched; | |
251 | ||
246 | 252 | public slots: |
247 | 253 | |
248 | 254 | /** display different cursor where editing available */ |
46 | 46 | */ |
47 | 47 | Preferences::Preferences(QObject *parent) : |
48 | 48 | QSettings("SWI-Prolog", "pqConsole", parent) |
49 | { | |
49 | { qDebug() << "Loading preferences from " << fileName(); | |
50 | ||
50 | 51 | console_font = value("console_font", QFont("courier", 12)).value<QFont>(); |
51 | 52 | wrapMode = static_cast<ConsoleEditBase::LineWrapMode>(value("wrapMode", ConsoleEditBase::WidgetWidth).toInt()); |
52 | 53 |
730 | 730 | ConsoleEdit::exec_sync s; |
731 | 731 | c->exec_func([&]() { |
732 | 732 | Preferences p; |
733 | qDebug() << "Opening font dialog"; | |
733 | 734 | QFont font = QFontDialog::getFont(&ok, p.console_font, c); |
735 | qDebug() << "ok = " << ok << "font = " << font; | |
734 | 736 | if (ok) |
735 | 737 | c->setFont(p.console_font = font); |
736 | 738 | s.go(); |
8 | 8 | modules=true |
9 | 9 | quiet=false |
10 | 10 | moduleoptions= |
11 | [ -z "$wiki" ] && wiki=false | |
12 | [ -z "$level" ] && level=+ | |
13 | ||
14 | export wiki level | |
11 | [ -z "$level" ] && level="=" | |
12 | ||
13 | export level | |
15 | 14 | |
16 | 15 | help() |
17 | 16 | { echo "Usage: `basename $0` option ... [version][..version] [path ...]" |
44 | 43 | shift |
45 | 44 | ;; |
46 | 45 | --wiki) |
47 | wiki=true | |
48 | 46 | shift |
49 | 47 | ;; |
50 | 48 | --nomodules) |
122 | 120 | header () |
123 | 121 | { hdr="$*" |
124 | 122 | |
125 | if [ "$wiki" = true ]; then | |
126 | echo ---$level $hdr | |
127 | else | |
128 | hdr="$*" | |
129 | eq=`echo $hdr | sed 's/./=/g'` | |
130 | echo $eq | |
131 | echo $hdr | |
132 | echo $eq | |
133 | fi | |
123 | hdr="$*" | |
124 | eq=`echo $hdr | sed "s/./$level/g"` | |
125 | echo $hdr | |
126 | echo $eq | |
134 | 127 | |
135 | 128 | echo |
136 | 129 | } |
182 | 175 | } |
183 | 176 | |
184 | 177 | if [ "$modules" = true ]; then |
185 | level="$level+" | |
178 | level="-" | |
186 | 179 | |
187 | 180 | echo |
188 | 181 |
0 | 0 | CMAKE_COMMAND=cmake |
1 | 1 | PGO_DIR=PGO-data |
2 | PGO_PROGRAM=../bench/run.pl | |
2 | SRC_DIR="$(dirname "$(dirname "$0")")" | |
3 | PGO_PROGRAM="${SRC_DIR}/bench/run.pl" | |
3 | 4 | |
4 | 5 | if [ "$1" = "--off" ]; then |
5 | 6 | ${CMAKE_COMMAND} -E echo "PGO: disabling" |
6 | ${CMAKE_COMMAND} -DPROFILE_GUIDED_OPTIMIZATION=OFF -G Ninja .. | |
7 | ${CMAKE_COMMAND} -DPROFILE_GUIDED_OPTIMIZATION=OFF -G Ninja ${SRC_DIR} | |
7 | 8 | ${CMAKE_COMMAND} -E remove_directory ${PGO_DIR} |
8 | 9 | ninja -t clean libswipl |
9 | 10 | ${CMAKE_COMMAND} -E echo "PGO: run ninja to complete rebuild" |
10 | 11 | else |
11 | ${CMAKE_COMMAND} -DPROFILE_GUIDED_OPTIMIZATION=GENERATE -G Ninja .. | |
12 | ${CMAKE_COMMAND} -DPROFILE_GUIDED_OPTIMIZATION=GENERATE -G Ninja ${SRC_DIR} | |
12 | 13 | ninja -t clean libswipl |
13 | 14 | ${CMAKE_COMMAND} -E echo "PGO: Compiling instrumented version" |
14 | 15 | ninja prolog_products |
23 | 24 | |
24 | 25 | ${SWIPL} -f none --no-threads ${PGO_PROGRAM} |
25 | 26 | |
26 | ${CMAKE_COMMAND} -DPROFILE_GUIDED_OPTIMIZATION=USE -G Ninja .. | |
27 | ${CMAKE_COMMAND} -DPROFILE_GUIDED_OPTIMIZATION=USE -G Ninja ${SRC_DIR} | |
27 | 28 | ninja -t clean libswipl |
28 | 29 | ${CMAKE_COMMAND} -E echo "PGO: Compiling optimized core" |
29 | 30 | ninja prolog_products |
67 | 67 | /* PLVERSION_TAG: a string, normally "", but for example "rc1" */ |
68 | 68 | |
69 | 69 | #ifndef PLVERSION |
70 | #define PLVERSION 80001 | |
70 | #define PLVERSION 80002 | |
71 | 71 | #endif |
72 | 72 | #ifndef PLVERSION_TAG |
73 | 73 | #define PLVERSION_TAG "" |
1199 | 1199 | :- begin_tests(mode_components1, [cleanup(abolish_all_tables)]). |
1200 | 1200 | |
1201 | 1201 | :- table |
1202 | p(lattice(orp/3)), | |
1203 | s(lattice(ors/3)). | |
1202 | p2(lattice(orp/3)), | |
1203 | s2(lattice(ors/3)). | |
1204 | 1204 | |
1205 | 1205 | orp(A,B,A+B). |
1206 | 1206 | ors(A,B,A-B). |
1207 | 1207 | |
1208 | p(A) :- | |
1209 | s(A). | |
1210 | ||
1211 | s(1). | |
1212 | s(2). | |
1208 | p2(A) :- | |
1209 | s2(A). | |
1210 | ||
1211 | s2(1). | |
1212 | s2(2). | |
1213 | 1213 | |
1214 | 1214 | test(component, [A == (1-2), nondet]) :- |
1215 | p(A). | |
1215 | p2(A). | |
1216 | 1216 | |
1217 | 1217 | :- end_tests(mode_components1). |
1218 | 1218 |
49 | 49 | #define ftello64 ftell |
50 | 50 | #define fseeko64 fseek |
51 | 51 | #else |
52 | #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) | |
52 | #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ | |
53 | || defined(__HAIKU__) | |
53 | 54 | #define fopen64 fopen |
54 | 55 | #define ftello64 ftello |
55 | 56 | #define fseeko64 fseeko |
39 | 39 | size_t top = b->top - b->base; |
40 | 40 | char *new; |
41 | 41 | |
42 | if ( b->max - b->top >= (int)minfree ) | |
42 | if ( b->max - b->top >= minfree ) | |
43 | 43 | return TRUE; |
44 | 44 | |
45 | 45 | if ( sz < 512 ) |
396 | 396 | |
397 | 397 | int |
398 | 398 | PL_unify_text(term_t term, term_t tail, PL_chars_t *text, int type) |
399 | { switch(type) | |
399 | { GET_LD | |
400 | ||
401 | switch(type) | |
400 | 402 | { case PL_ATOM: |
401 | 403 | { atom_t a = textToAtom(text); |
402 | 404 | |
425 | 427 | |
426 | 428 | if ( text->length == 0 ) |
427 | 429 | { if ( tail ) |
428 | { GET_LD | |
429 | PL_put_term(tail, term); | |
430 | { PL_put_term(tail, term); | |
430 | 431 | return TRUE; |
431 | 432 | } else |
432 | 433 | { return PL_unify_nil(term); |
433 | 434 | } |
434 | 435 | } else |
435 | { GET_LD | |
436 | term_t l = PL_new_term_ref(); | |
436 | { term_t l = PL_new_term_ref(); | |
437 | 437 | Word p0, p; |
438 | 438 | |
439 | 439 | switch(text->encoding) |
192 | 192 | { linger_list *c = allocHeapOrHalt(sizeof(*c)); |
193 | 193 | linger_list *o; |
194 | 194 | |
195 | c->object = object; | |
196 | c->unalloc = unalloc; | |
195 | c->generation = global_generation(); | |
196 | c->object = object; | |
197 | c->unalloc = unalloc; | |
197 | 198 | |
198 | 199 | do |
199 | 200 | { o = *list; |
202 | 203 | } |
203 | 204 | |
204 | 205 | void |
205 | free_lingering(linger_list *list) | |
206 | { linger_list *n; | |
207 | ||
208 | for(; list; list=n) | |
209 | { n = list->next; | |
210 | (*list->unalloc)(list->object); | |
211 | freeHeap(list, sizeof(*list)); | |
206 | free_lingering(linger_list **list, gen_t generation) | |
207 | { linger_list **p = list; | |
208 | linger_list *c = *list; | |
209 | ||
210 | while ( c ) | |
211 | { if ( c->generation < generation ) | |
212 | { while ( !COMPARE_AND_SWAP(p, c, c->next) ) | |
213 | { p = &(*p)->next; | |
214 | } | |
215 | (*c->unalloc)(c->object); | |
216 | freeHeap(c, sizeof(*c)); | |
217 | } else | |
218 | { p = &(*p)->next; | |
219 | } | |
220 | c = *p; | |
212 | 221 | } |
213 | 222 | } |
214 | 223 |
76 | 76 | |
77 | 77 | typedef struct linger_list |
78 | 78 | { struct linger_list *next; /* Next lingering object */ |
79 | gen_t generation; /* Linger generation */ | |
79 | 80 | void *object; /* The lingering data */ |
80 | 81 | void (*unalloc)(void* obj); /* actually free the object */ |
81 | 82 | } linger_list; |
82 | 83 | |
83 | 84 | COMMON(void) linger(linger_list** list, void (*unalloc)(void *), void *object); |
84 | COMMON(void) free_lingering(linger_list *list); | |
85 | COMMON(void) free_lingering(linger_list **list, gen_t generation); | |
85 | 86 | |
86 | 87 | |
87 | 88 | /******************************* |
1058 | 1058 | fail; |
1059 | 1059 | #endif |
1060 | 1060 | case V_FLOAT: |
1061 | if ( !check_float(n->value.f) ) | |
1062 | return FALSE; | |
1061 | 1063 | if ( (flags & TOINT_CONVERT_FLOAT) ) |
1062 | 1064 | { if ( double_in_int64_range(n->value.f) ) |
1063 | 1065 | { int64_t l = (int64_t)n->value.f; |
2260 | 2262 | promoteToMPQNumber(r); |
2261 | 2263 | succeed; |
2262 | 2264 | case V_FLOAT: |
2263 | { double e0 = n1->value.f, p0 = 0.0, q0 = 1.0; | |
2265 | { if ( !check_float(n1->value.f) ) | |
2266 | return FALSE; | |
2267 | ||
2268 | double e0 = n1->value.f, p0 = 0.0, q0 = 1.0; | |
2264 | 2269 | double e1 = -1.0, p1 = 1.0, q1 = 0.0; |
2265 | 2270 | double d; |
2266 | 2271 | |
2905 | 2910 | } |
2906 | 2911 | #endif |
2907 | 2912 | case V_FLOAT: |
2908 | { if ( n1->value.f <= PLMAXINT && n1->value.f >= PLMININT ) | |
2913 | { if ( !check_float(n1->value.f) ) | |
2914 | return FALSE; | |
2915 | if ( n1->value.f <= PLMAXINT && n1->value.f >= PLMININT ) | |
2909 | 2916 | { if ( n1->value.f > 0 ) |
2910 | 2917 | { r->value.i = (int64_t)(n1->value.f + 0.5); |
2911 | 2918 | if ( r->value.i < 0 ) /* Why can this happen? */ |
2968 | 2975 | succeed; |
2969 | 2976 | #endif |
2970 | 2977 | case V_FLOAT: |
2971 | { | |
2978 | { if ( !check_float(n1->value.f) ) | |
2979 | return FALSE; | |
2972 | 2980 | #ifdef HAVE_FLOOR |
2973 | 2981 | r->type = V_FLOAT; |
2974 | 2982 | r->value.f = floor(n1->value.f); |
3021 | 3029 | succeed; |
3022 | 3030 | #endif |
3023 | 3031 | case V_FLOAT: |
3024 | { | |
3032 | { if ( !check_float(n1->value.f) ) | |
3033 | return FALSE; | |
3025 | 3034 | #ifdef HAVE_CEIL |
3026 | r->type = V_FLOAT; | |
3027 | r->value.f = ceil(n1->value.f); | |
3028 | if ( !toIntegerNumber(r, TOINT_CONVERT_FLOAT|TOINT_TRUNCATE) ) | |
3029 | { return PL_error("ceil", 1, NULL, ERR_EVALUATION, ATOM_int_overflow); | |
3030 | } | |
3035 | r->type = V_FLOAT; | |
3036 | r->value.f = ceil(n1->value.f); | |
3037 | if ( !toIntegerNumber(r, TOINT_CONVERT_FLOAT|TOINT_TRUNCATE) ) | |
3038 | { return PL_error("ceil", 1, NULL, ERR_EVALUATION, ATOM_int_overflow); | |
3039 | } | |
3031 | 3040 | #else /*HAVE_CEIL*/ |
3032 | if ( n1->value.f > (double)PLMININT && n1->value.f < (double)PLMAXINT ) | |
3033 | { r->value.i = (int64_t)n1->value.f; | |
3034 | if ( (double)r->value.i < n1->value.f ) | |
3035 | r->value.i++; | |
3036 | r->type = V_INTEGER; | |
3037 | } else | |
3038 | { | |
3039 | #ifdef O_GMP | |
3040 | r->type = V_MPZ; | |
3041 | mpz_init_set_d(r->value.mpz, n1->value.f); | |
3042 | if ( mpz_get_d(r->value.mpz) < n1->value.f ) | |
3043 | mpz_add_ui(r->value.mpz, r->value.mpz, 1L); | |
3041 | if ( n1->value.f > (double)PLMININT && n1->value.f < (double)PLMAXINT ) | |
3042 | { r->value.i = (int64_t)n1->value.f; | |
3043 | if ( (double)r->value.i < n1->value.f ) | |
3044 | r->value.i++; | |
3045 | r->type = V_INTEGER; | |
3046 | } else | |
3047 | { | |
3048 | #ifdef O_GMP | |
3049 | r->type = V_MPZ; | |
3050 | mpz_init_set_d(r->value.mpz, n1->value.f); | |
3051 | if ( mpz_get_d(r->value.mpz) < n1->value.f ) | |
3052 | mpz_add_ui(r->value.mpz, r->value.mpz, 1L); | |
3044 | 3053 | #else |
3045 | return PL_error("ceil", 1, NULL, ERR_EVALUATION, ATOM_int_overflow); | |
3046 | #endif | |
3047 | } | |
3054 | return PL_error("ceil", 1, NULL, ERR_EVALUATION, ATOM_int_overflow); | |
3055 | #endif | |
3056 | } | |
3048 | 3057 | #endif /*HAVE_CEIL*/ |
3049 | 3058 | } |
3050 | 3059 | } |
3784 | 3784 | * ATOMIC (INTERNAL) * |
3785 | 3785 | *******************************/ |
3786 | 3786 | |
3787 | #undef _PL_unify_atomic | |
3788 | ||
3787 | 3789 | PL_atomic_t |
3788 | 3790 | _PL_get_atomic(term_t t) |
3789 | 3791 | { GET_LD |
3803 | 3805 | { GET_LD |
3804 | 3806 | setHandle(t, a); |
3805 | 3807 | } |
3808 | ||
3809 | #define _PL_unify_atomic(t, a) PL_unify_atom__LD(t, a PASS_LD) | |
3806 | 3810 | |
3807 | 3811 | |
3808 | 3812 | /******************************* |
3993 | 3993 | #endif |
3994 | 3994 | |
3995 | 3995 | if ( verbose ) |
3996 | { if ( !printMessage(ATOM_informational, | |
3997 | PL_FUNCTOR_CHARS, "gc", 1, | |
3998 | PL_CHARS, "start") ) | |
3999 | return FALSE; | |
4000 | } | |
3996 | Sdprintf("%% GC: "); | |
4001 | 3997 | |
4002 | 3998 | get_vmi_state(LD->query, &state); |
4003 | 3999 | safeLTop = lTop; |
4129 | 4125 | #endif |
4130 | 4126 | leaveGC(PASS_LD1); |
4131 | 4127 | |
4132 | if ( verbose && | |
4133 | !printMessage(ATOM_informational, | |
4134 | PL_FUNCTOR_CHARS, "gc", 1, | |
4135 | PL_FUNCTOR_CHARS, "done", 7, | |
4136 | PL_INTPTR, ggar, | |
4137 | PL_INTPTR, tgar, | |
4138 | PL_DOUBLE, (double)t, | |
4139 | PL_INTPTR, usedStack(global), | |
4140 | PL_INTPTR, usedStack(trail), | |
4141 | PL_INTPTR, roomStack(global), | |
4142 | PL_INTPTR, roomStack(trail)) ) | |
4143 | return FALSE; | |
4128 | if ( verbose ) | |
4129 | Sdprintf("gained (g+t) %zd+%zd in %.3f sec; used %zd+%zd; free %zd+%zd\n", | |
4130 | ggar, tgar, (double)t, | |
4131 | usedStack(global), usedStack(trail), | |
4132 | roomStack(global), roomStack(trail)); | |
4144 | 4133 | |
4145 | 4134 | return shiftTightStacks(); |
4146 | 4135 | } |
243 | 243 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
244 | 244 | |
245 | 245 | #ifndef __unix__ |
246 | #if defined(_AIX) || defined(__APPLE__) || defined(__unix) || defined(__BEOS__) || defined(__NetBSD__) | |
246 | #if defined(_AIX) || defined(__APPLE__) || defined(__unix) || defined(__BEOS__) || defined(__NetBSD__) || defined(__HAIKU__) | |
247 | 247 | #define __unix__ 1 |
248 | 248 | #endif |
249 | 249 | #endif |
931 | 931 | #define FR_SKIPPED (0x0002) /* We have skipped on this frame */ |
932 | 932 | #define FR_MARKED (0x0004) /* GC */ |
933 | 933 | #define FR_MARKED_PRED (0x0008) /* GC predicates/clauses */ |
934 | #define FR_WATCHED (0x0010) /* GUI debugger */ | |
934 | #define FR_DEBUG (0x0010) /* GUI debugger */ | |
935 | 935 | #define FR_CATCHED (0x0020) /* Frame caught an exception */ |
936 | 936 | #define FR_INBOX (0x0040) /* Inside box (for REDO in built-in) */ |
937 | 937 | #define FR_CONTEXT (0x0080) /* fr->context is set */ |
938 | #define FR_CLEANUP (0x0100) /* setup_call_cleanup/4: marked for cleanup */ | |
938 | #define FR_CLEANUP (0x0100) /* setup_call_cleanup/4 */ | |
939 | 939 | #define FR_INRESET (0x0200) /* Continuations: inside reset/3 */ |
940 | #define FR_WATCHED (FR_CLEANUP|FR_DEBUG) | |
941 | ||
940 | 942 | #define FR_MAGIC_MASK (0xfffff000) |
941 | 943 | #define FR_MAGIC_MASK2 (0xffff0000) |
942 | 944 | #define FR_MAGIC (0x549d5000) |
339 | 339 | if ( str_number((unsigned char *)s, &q, &n, FALSE) == NUM_OK && |
340 | 340 | intNumber(&n) ) |
341 | 341 | { switch((int)*q) |
342 | { case 'k': | |
342 | { case 0: | |
343 | return (size_t)n.value.i; | |
344 | case 'k': | |
343 | 345 | case 'K': |
344 | 346 | return (size_t)n.value.i K; |
345 | 347 | case 'm': |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2010-2016, University of Amsterdam | |
5 | Copyright (c) 2010-2019, 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 |
100 | 101 | #define PL_put_term(t1, t2) PL_put_term__LD(t1, t2 PASS_LD) |
101 | 102 | #define PL_get_functor(t, f) PL_get_functor__LD(t, f PASS_LD) |
102 | 103 | #define PL_unify_atom(t, a) PL_unify_atom__LD(t, a PASS_LD) |
104 | #define _PL_unify_atomic(t, a) PL_unify_atom__LD(t, a PASS_LD) | |
103 | 105 | #define PL_unify_pointer(t, p) PL_unify_pointer__LD(t, p PASS_LD) |
104 | 106 | #define PL_is_variable(t) PL_is_variable__LD(t PASS_LD) |
105 | 107 | #define PL_is_atomic(t) PL_is_atomic__LD(t PASS_LD) |
345 | 345 | PL_reset_term_refs(g); |
346 | 346 | fail; |
347 | 347 | } |
348 | ||
349 | /* Quick check for '$sig_atomic'(true) resulting from the call_cleanup | |
350 | * series | |
351 | */ | |
352 | if ( fd == FUNCTOR_true0 ) | |
353 | return TRUE; | |
348 | 354 | |
349 | 355 | proc = resolveProcedure(fd, module); |
350 | 356 |
1466 | 1466 | |
1467 | 1467 | static void |
1468 | 1468 | freeLingeringDefinition(Definition def, DirtyDefInfo ddi) |
1469 | { linger_list *c; | |
1470 | ||
1471 | do | |
1472 | { if ( !(c=def->lingering) ) | |
1473 | return; | |
1474 | if ( ddi->oldest_generation != GEN_MAX ) | |
1475 | return; | |
1476 | } while( !COMPARE_AND_SWAP(&def->lingering, c, NULL) ); | |
1477 | ||
1478 | free_lingering(c); | |
1469 | { gen_t gen = ddi->oldest_generation == GEN_MAX ? global_generation() | |
1470 | : ddi->oldest_generation; | |
1471 | free_lingering(&def->lingering, gen); | |
1479 | 1472 | } |
1480 | 1473 | |
1481 | 1474 |
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-2017, University of Amsterdam | |
5 | Copyright (c) 1985-2010, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
1916 | 1916 | |
1917 | 1917 | bool |
1918 | 1918 | unifyKey(term_t key, word val) |
1919 | { if ( isAtom(val) || isTaggedInt(val) ) | |
1919 | { GET_LD | |
1920 | ||
1921 | if ( isAtom(val) || isTaggedInt(val) ) | |
1920 | 1922 | { return _PL_unify_atomic(key, val); |
1921 | 1923 | } else |
1922 | { GET_LD | |
1923 | ||
1924 | return PL_unify_functor(key, (functor_t) val); | |
1924 | { return PL_unify_functor(key, (functor_t) val); | |
1925 | 1925 | } |
1926 | 1926 | } |
1927 | 1927 |
1212 | 1212 | { unprepareSignal(sign); |
1213 | 1213 | } else if ( a == ATOM_throw ) |
1214 | 1214 | { sh = prepareSignal(sign); |
1215 | set(sh, PLSIG_THROW); | |
1216 | clear(sh, PLSIG_SYNC); | |
1215 | set(sh, PLSIG_THROW|PLSIG_SYNC); | |
1217 | 1216 | sh->handler = NULL; |
1218 | 1217 | sh->predicate = NULL; |
1219 | 1218 | } else |
5333 | 5333 | (attr->flags & PL_THREAD_NOT_DETACHED) == 0; |
5334 | 5334 | info->open_count = 1; |
5335 | 5335 | |
5336 | copy_local_data(ldnew, ldmain, attr->max_queue_size); | |
5336 | copy_local_data(ldnew, ldmain, attr ? attr->max_queue_size : 0); | |
5337 | 5337 | |
5338 | 5338 | if ( !initialise_thread(info) ) |
5339 | 5339 | { free_thread_info(info); |
1579 | 1579 | resetTracer(void) |
1580 | 1580 | { GET_LD |
1581 | 1581 | |
1582 | #if defined(O_INTERRUPT) && defined(SIGINT) | |
1583 | if ( truePrologFlag(PLFLAG_SIGNALS) ) | |
1584 | PL_signal(SIGINT, interruptHandler); | |
1585 | #endif | |
1586 | ||
1587 | 1582 | debugstatus.tracing = FALSE; |
1588 | 1583 | debugstatus.debugging = DBG_OFF; |
1589 | 1584 | debugstatus.suspendTrace = 0; |
1761 | 1756 | EXCEPTION_PORT; |
1762 | 1757 | debugstatus.showContext = FALSE; |
1763 | 1758 | |
1759 | #if defined(O_INTERRUPT) && defined(SIGINT) | |
1760 | if ( truePrologFlag(PLFLAG_SIGNALS) ) | |
1761 | PL_signal(SIGINT, interruptHandler); | |
1762 | #endif | |
1763 | ||
1764 | 1764 | resetTracer(); |
1765 | 1765 | } |
1766 | 1766 | |
2096 | 2096 | if ( !PL_strip_module(value, &m, value) ) |
2097 | 2097 | return FALSE; |
2098 | 2098 | |
2099 | set(fr, FR_WATCHED); /* explicit call to do this? */ | |
2099 | set(fr, FR_DEBUG); /* explicit call to do this? */ | |
2100 | 2100 | |
2101 | 2101 | if ( key == ATOM_argument && arity == 1 ) |
2102 | 2102 | { term_t arg = PL_new_term_ref(); |
1241 | 1241 | trie_node *child; |
1242 | 1242 | size_t gsize; |
1243 | 1243 | unsigned int nvars; |
1244 | struct trie_choice *next; | |
1245 | struct trie_choice *prev; | |
1246 | 1244 | } trie_choice; |
1247 | 1245 | |
1248 | 1246 | typedef struct |
1249 | { trie_choice *head; /* head of trie nodes */ | |
1250 | trie_choice *tail; /* tail of trie nodes */ | |
1251 | trie *trie; /* trie we operate on */ | |
1247 | { trie *trie; /* trie we operate on */ | |
1248 | int allocated; | |
1249 | tmp_buffer choicepoints; /* Stack of trie state choicepoints */ | |
1252 | 1250 | } trie_gen_state; |
1251 | ||
1252 | ||
1253 | static void | |
1254 | init_trie_state(trie_gen_state *state, trie *trie) | |
1255 | { state->trie = trie; | |
1256 | state->allocated = FALSE; | |
1257 | initBuffer(&state->choicepoints); | |
1258 | } | |
1259 | ||
1260 | ||
1261 | #define base_choice(state) baseBuffer(&state->choicepoints, trie_choice) | |
1262 | #define top_choice(state) topBuffer(&state->choicepoints, trie_choice) | |
1253 | 1263 | |
1254 | 1264 | |
1255 | 1265 | static void |
1256 | 1266 | clear_trie_state(trie_gen_state *state) |
1257 | { trie_choice *ch, *next; | |
1258 | ||
1259 | for(ch=state->head; ch; ch=next) | |
1260 | { next = ch->next; | |
1261 | ||
1262 | if ( ch->choice.table ) | |
1263 | freeTableEnum(ch->choice.table); | |
1264 | PL_free(ch); | |
1265 | } | |
1267 | { trie_choice *chp = base_choice(state); | |
1268 | trie_choice *top = top_choice(state); | |
1269 | ||
1270 | for(; chp < top; chp++) | |
1271 | { if ( chp->choice.table ) | |
1272 | freeTableEnum(chp->choice.table); | |
1273 | } | |
1274 | ||
1275 | discardBuffer(&state->choicepoints); | |
1266 | 1276 | |
1267 | 1277 | release_trie(state->trie); |
1278 | ||
1279 | if ( state->allocated ) | |
1280 | freeForeignState(state, sizeof(*state)); | |
1268 | 1281 | } |
1269 | 1282 | |
1270 | 1283 | |
1271 | 1284 | trie_choice * |
1272 | 1285 | add_choice(trie_gen_state *state, trie_node *node) |
1273 | { trie_choice *ch = PL_malloc(sizeof(*ch)); | |
1274 | trie_children children = node->children; | |
1275 | size_t gsize = state->tail ? state->tail->gsize : 0; | |
1276 | unsigned int nvars = state->tail ? state->tail->nvars : 0; | |
1286 | { trie_children children = node->children; | |
1287 | trie_choice *ch = allocFromBuffer(&state->choicepoints, sizeof(*ch)); | |
1288 | size_t gsize; | |
1289 | unsigned int nvars; | |
1290 | ||
1291 | if ( ch > base_choice(state) ) | |
1292 | { trie_choice *prev = ch-1; | |
1293 | gsize = prev->gsize; | |
1294 | nvars = prev->nvars; | |
1295 | } else | |
1296 | { gsize = 0; | |
1297 | nvars = 0; | |
1298 | } | |
1277 | 1299 | |
1278 | 1300 | if ( children.any ) |
1279 | 1301 | { switch( children.any->type ) |
1313 | 1335 | ch->gsize = gsize; |
1314 | 1336 | ch->nvars = nvars; |
1315 | 1337 | |
1316 | ch->next = NULL; | |
1317 | ch->prev = state->tail; | |
1318 | if ( state->tail ) | |
1319 | state->tail->next = ch; | |
1320 | else | |
1321 | state->head = ch; | |
1322 | state->tail = ch; | |
1323 | ||
1324 | 1338 | return ch; |
1325 | 1339 | } |
1326 | 1340 | |
1335 | 1349 | } |
1336 | 1350 | |
1337 | 1351 | |
1338 | static trie_choice * | |
1339 | previous_choice(trie_gen_state *state) | |
1340 | { trie_choice *ch = state->tail; | |
1341 | ||
1342 | if ( ch->choice.table ) | |
1343 | freeTableEnum(ch->choice.table); | |
1344 | state->tail = ch->prev; | |
1345 | if ( state->tail ) | |
1346 | state->tail->next = NULL; | |
1347 | else | |
1348 | state->head = NULL; | |
1349 | PL_free(ch); | |
1350 | ||
1351 | return state->tail; | |
1352 | } | |
1353 | ||
1354 | ||
1355 | 1352 | static int |
1356 | 1353 | advance_node(trie_choice *ch) |
1357 | 1354 | { if ( ch->choice.table ) |
1371 | 1368 | |
1372 | 1369 | static int |
1373 | 1370 | next_choice(trie_gen_state *state) |
1374 | { trie_choice *ch; | |
1375 | ||
1376 | for( ch = state->tail; ch; ch = previous_choice(state) ) | |
1371 | { trie_choice *btm = base_choice(state); | |
1372 | trie_choice *ch = top_choice(state)-1; | |
1373 | ||
1374 | while(ch >= btm) | |
1377 | 1375 | { if ( advance_node(ch) && |
1378 | 1376 | descent_node(state, ch) ) |
1379 | 1377 | return TRUE; |
1378 | ||
1379 | state->choicepoints.top = (char*)ch; | |
1380 | ch--; | |
1380 | 1381 | } |
1381 | 1382 | |
1382 | 1383 | return FALSE; |
1386 | 1387 | static int |
1387 | 1388 | put_trie_path(term_t term, Word value, trie_gen_state *gstate ARG_LD) |
1388 | 1389 | { int rc = TRUE; |
1389 | trie_choice *ch; | |
1390 | 1390 | build_state bstate; |
1391 | trie_choice *lch = top_choice(gstate)-1; | |
1391 | 1392 | |
1392 | 1393 | if ( init_build_state(&bstate, |
1393 | 1394 | gstate->trie, |
1394 | gstate->tail->gsize, | |
1395 | gstate->tail->nvars+1 PASS_LD) ) | |
1396 | { | |
1395 | lch->gsize, | |
1396 | lch->nvars+1 PASS_LD) ) | |
1397 | { trie_choice *ch = base_choice(gstate); | |
1398 | trie_choice *top = top_choice(gstate); | |
1397 | 1399 | #ifndef NDEBUG |
1398 | Word gok = gTop + gstate->tail->gsize; | |
1400 | Word gok = gTop + lch->gsize; | |
1399 | 1401 | #endif |
1400 | 1402 | |
1401 | for( ch = gstate->head; ch; ch = ch->next ) | |
1403 | for( ; ch < top; ch++ ) | |
1402 | 1404 | { if ( !eval_key(&bstate, ch->key PASS_LD) ) |
1403 | 1405 | { rc = FALSE; |
1404 | 1406 | break; |
1405 | } | |
1406 | if ( !ch->next ) | |
1407 | { *value = ch->child->value; | |
1408 | 1407 | } |
1409 | 1408 | } |
1410 | 1409 | |
1414 | 1413 | gTop = bstate.gp; |
1415 | 1414 | *valTermRef(term) = bstate.result; |
1416 | 1415 | DEBUG(CHK_SECURE, PL_check_data(term)); |
1416 | *value = ch[-1].child->value; | |
1417 | 1417 | } |
1418 | 1418 | } else |
1419 | 1419 | rc = FALSE; |
1436 | 1436 | { trie *trie; |
1437 | 1437 | |
1438 | 1438 | if ( get_trie(A1, &trie) ) |
1439 | { state = &state_buf; | |
1440 | memset(state, 0, sizeof(*state)); | |
1441 | ||
1442 | if ( trie->root.children.any ) | |
1439 | { if ( trie->root.children.any ) | |
1443 | 1440 | { acquire_trie(trie); |
1444 | state->trie = trie; | |
1441 | state = &state_buf; | |
1442 | init_trie_state(state, trie); | |
1445 | 1443 | if ( !descent_node(state, add_choice(state, &trie->root)) && |
1446 | 1444 | !next_choice(state) ) |
1447 | 1445 | { clear_trie_state(state); |
1458 | 1456 | case FRG_CUTTED: |
1459 | 1457 | state = CTX_PTR; |
1460 | 1458 | clear_trie_state(state); |
1461 | freeForeignState(state, sizeof(*state)); | |
1462 | 1459 | return TRUE; |
1463 | 1460 | default: |
1464 | 1461 | assert(0); |
1468 | 1465 | key = PL_new_term_ref(); |
1469 | 1466 | fid = PL_open_foreign_frame(); |
1470 | 1467 | |
1471 | for( ; state->head; next_choice(state) ) | |
1468 | for( ; !isEmptyBuffer(&state->choicepoints); next_choice(state) ) | |
1472 | 1469 | { if ( !put_trie_path(key, &value, state PASS_LD) ) |
1473 | 1470 | { PL_close_foreign_frame(fid); |
1474 | 1471 | return FALSE; /* resource error */ |
1475 | 1472 | } |
1476 | 1473 | if ( PL_unify(A2, key) && unify_value(A3, value PASS_LD) ) |
1477 | 1474 | { if ( next_choice(state) ) |
1478 | { if ( state == &state_buf ) | |
1479 | { state = allocForeignState(sizeof(*state)); | |
1480 | memcpy(state, &state_buf, sizeof(*state)); | |
1475 | { if ( !state->allocated ) | |
1476 | { trie_gen_state *nstate = allocForeignState(sizeof(*state)); | |
1477 | TmpBuffer nchp = &nstate->choicepoints; | |
1478 | TmpBuffer ochp = &state->choicepoints; | |
1479 | ||
1480 | nstate->trie = state->trie; | |
1481 | nstate->allocated = TRUE; | |
1482 | if ( ochp->base == ochp->static_buffer ) | |
1483 | { size_t bytes = ochp->top - ochp->base; | |
1484 | initBuffer(nchp); | |
1485 | nchp->top = nchp->base + bytes; | |
1486 | memcpy(nchp->base, ochp->base, bytes); | |
1487 | } else | |
1488 | { nchp->base = ochp->base; | |
1489 | nchp->top = ochp->top; | |
1490 | nchp->max = ochp->max; | |
1491 | } | |
1492 | ||
1493 | state = nstate; | |
1481 | 1494 | } |
1482 | 1495 | PL_close_foreign_frame(fid); |
1483 | 1496 | ForeignRedoPtr(state); |
4153 | 4153 | THROW_EXCEPTION; |
4154 | 4154 | |
4155 | 4155 | newChoice(CHP_CATCH, FR PASS_LD); |
4156 | set(FR, FR_WATCHED|FR_CLEANUP); | |
4156 | set(FR, FR_CLEANUP); | |
4157 | 4157 | /* = B_VAR1 */ |
4158 | 4158 | *argFrameP(lTop, 0) = linkVal(argFrameP(FR, 1)); |
4159 | 4159 | |
4336 | 4336 | !resourceException(exception_term PASS_LD) ) |
4337 | 4337 | { int rc; |
4338 | 4338 | |
4339 | SAVE_REGISTERS(qid); | |
4340 | exceptionUnwindGC(); | |
4341 | LOAD_REGISTERS(qid); | |
4342 | 4339 | SAVE_REGISTERS(qid); |
4343 | 4340 | rc = exception_hook(qid, consTermRef(FR), catchfr_ref PASS_LD); |
4344 | 4341 | LOAD_REGISTERS(qid); |
670 | 670 | fr = (LocalFrame)valTermRef(fref); |
671 | 671 | } |
672 | 672 | |
673 | return callEventHook(PLEV_FRAMEFINISHED, fr); | |
673 | if ( true(fr, FR_DEBUG) ) | |
674 | return callEventHook(PLEV_FRAMEFINISHED, fr); | |
675 | ||
676 | return TRUE; | |
674 | 677 | } |
675 | 678 | |
676 | 679 | |
1591 | 1594 | setVar(*valTermRef(LD->exception.pending)); |
1592 | 1595 | } |
1593 | 1596 | |
1594 | LD->stacks.global.gced_size = 0; | |
1595 | LD->stacks.trail.gced_size = 0; | |
1597 | if ( outofstack && outofstack->gc ) | |
1598 | { LD->stacks.global.gced_size = 0; | |
1599 | LD->stacks.trail.gced_size = 0; | |
1600 | } | |
1596 | 1601 | |
1597 | 1602 | if ( !considerGarbageCollect((Stack)NULL) ) |
1598 | 1603 | { trimStacks((outofstack != NULL) PASS_LD); |
1599 | } else if ( outofstack != NULL ) | |
1604 | } else | |
1600 | 1605 | { trimStacks(FALSE PASS_LD); /* just re-enable the spare stacks */ |
1601 | LD->trim_stack_requested = TRUE; /* next time with resize */ | |
1606 | if ( outofstack != NULL ) | |
1607 | LD->trim_stack_requested = TRUE; /* next time with resize */ | |
1602 | 1608 | } |
1603 | 1609 | |
1604 | 1610 | LD->exception.processing = FALSE; |
446 | 446 | close_zipper(zipper *z) |
447 | 447 | { zipFile zf; |
448 | 448 | unzFile uzf; |
449 | char *path; | |
449 | 450 | int rc = 0; |
450 | 451 | |
451 | 452 | if ( (zf=z->writer) ) |
455 | 456 | { z->reader = NULL; |
456 | 457 | rc = unzClose(uzf); |
457 | 458 | } |
458 | if ( z->path ) | |
459 | { free((char*)z->path); | |
460 | z->path = NULL; | |
459 | if ( (path=(char*)z->path) ) | |
460 | { z->path = NULL; | |
461 | free(path); | |
461 | 462 | } |
462 | 463 | if ( z->input.any ) |
463 | 464 | { switch(z->input_type) |
464 | 465 | { case ZIP_STREAM: |
465 | 466 | if ( true(z, ZIP_CLOSE_STREAM_ON_CLOSE) ) |
466 | Sclose(z->input.stream); | |
467 | { IOSTREAM *in = z->input.stream; | |
468 | ||
469 | z->input.stream = NULL; | |
470 | Sclose(in); | |
471 | } | |
467 | 472 | break; |
468 | 473 | default: |
469 | 474 | break; |
Binary diff not shown