New upstream version 8.2.4+dfsg
Lev Lamberov
3 years ago
73 | 73 | include(QLF) |
74 | 74 | include(PackageSelection) |
75 | 75 | include(Dependencies) |
76 | include(DocDepends) | |
76 | 77 | |
77 | 78 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) |
78 | 79 | set_install_prefix() |
1379 | 1379 | sub_atom(Name, 0, _, _, '__aux_meta_call_'). |
1380 | 1380 | |
1381 | 1381 | compile_meta(CallIn, CallOut, M, Term, (CallOut :- Body)) :- |
1382 | term_variables(Term, AllVars), | |
1382 | replace_subterm(CallIn, true, Term, Term2), | |
1383 | term_variables(Term2, AllVars), | |
1383 | 1384 | term_variables(CallIn, InVars), |
1384 | 1385 | intersection_eq(InVars, AllVars, HeadVars), |
1385 | variant_sha1(CallIn+HeadVars, Hash), | |
1386 | copy_term_nat(CallIn+HeadVars, NAT), | |
1387 | variant_sha1(NAT, Hash), | |
1386 | 1388 | atom_concat('__aux_meta_call_', Hash, AuxName), |
1387 | 1389 | expand_goal(CallIn, _Pos0, Body, _Pos, M, [], (CallOut:-CallIn), []), |
1388 | 1390 | length(HeadVars, Arity), |
1391 | 1393 | ; HeadArgs = HeadVars |
1392 | 1394 | ), |
1393 | 1395 | CallOut =.. [AuxName|HeadArgs]. |
1396 | ||
1397 | %! replace_subterm(From, To, TermIn, TermOut) | |
1398 | % | |
1399 | % Replace instances (==/2) of From inside TermIn by To. | |
1400 | ||
1401 | replace_subterm(From, To, TermIn, TermOut) :- | |
1402 | From == TermIn, | |
1403 | !, | |
1404 | TermOut = To. | |
1405 | replace_subterm(From, To, TermIn, TermOut) :- | |
1406 | compound(TermIn), | |
1407 | compound_name_arity(TermIn, Name, Arity), | |
1408 | Arity > 0, | |
1409 | !, | |
1410 | compound_name_arity(TermOut, Name, Arity), | |
1411 | replace_subterm_compound(1, Arity, From, To, TermIn, TermOut). | |
1412 | replace_subterm(_, _, Term, Term). | |
1413 | ||
1414 | replace_subterm_compound(I, Arity, From, To, TermIn, TermOut) :- | |
1415 | I =< Arity, | |
1416 | !, | |
1417 | arg(I, TermIn, A1), | |
1418 | arg(I, TermOut, A2), | |
1419 | replace_subterm(From, To, A1, A2), | |
1420 | I2 is I+1, | |
1421 | replace_subterm_compound(I2, Arity, From, To, TermIn, TermOut). | |
1422 | replace_subterm_compound(_I, _Arity, _From, _To, _TermIn, _TermOut). | |
1423 | ||
1394 | 1424 | |
1395 | 1425 | %! intersection_eq(+Small, +Big, -Shared) is det. |
1396 | 1426 | % |
301 | 301 | ; var(Goal) |
302 | 302 | -> ( Arity == 0 |
303 | 303 | -> ( atom(Name) |
304 | -> Goal = Name | |
305 | ; Name == [] | |
304 | 306 | -> Goal = Name |
305 | 307 | ; blob(Name, closure) |
306 | 308 | -> Goal = Name |
1071 | 1073 | ; Dirs = Defaults |
1072 | 1074 | ), |
1073 | 1075 | '$member'(Dir, Dirs), |
1076 | Dir \== '', | |
1074 | 1077 | exists_directory(Dir). |
1075 | 1078 | |
1076 | 1079 | '$path_sep'(Char) :- |
94 | 94 | translate_message2(error(resource_error(tripwire(Wire, Context)), _)) --> |
95 | 95 | !, |
96 | 96 | tripwire_message(Wire, Context). |
97 | translate_message2(error(existence_error(reset, Ball), SWI)) --> | |
98 | swi_location(SWI), | |
99 | tabling_existence_error(Ball, SWI). | |
97 | 100 | translate_message2(error(ISO, SWI)) --> |
98 | 101 | swi_location(SWI), |
99 | 102 | term_message(ISO), |
314 | 317 | domain(Domain) --> |
315 | 318 | ['`~w\''-[Domain] ]. |
316 | 319 | |
320 | %! tabling_existence_error(+Ball, +Context)// | |
321 | % | |
322 | % Called on invalid shift/1 calls. Track those that result from | |
323 | % tabling errors. | |
324 | ||
325 | tabling_existence_error(Ball, Context) --> | |
326 | { table_shift_ball(Ball) }, | |
327 | [ 'Tabling dependency error' ], | |
328 | swi_extra(Context). | |
329 | ||
330 | table_shift_ball(dependency(_Head)). | |
331 | table_shift_ball(dependency(_Skeleton, _Trie, _Mono)). | |
332 | table_shift_ball(call_info(_Skeleton, _Status)). | |
333 | table_shift_ball(call_info(_GenSkeleton, _Skeleton, _Status)). | |
334 | ||
335 | %! dwim_predicates(+PI, -Dwims) | |
336 | % | |
337 | % Find related predicate indicators. | |
338 | ||
317 | 339 | dwim_predicates(Module:Name/_Arity, Dwims) :- |
318 | 340 | !, |
319 | 341 | findall(Dwim, dwim_predicate(Module:Name, Dwim), Dwims). |
0 | if(INSTALL_DOCUMENTATION OR WARN_NO_DOCUMENTATION) | |
1 | ||
2 | # Verify all packages required to build the HTML documentation are | |
3 | # present. | |
4 | ||
5 | function(check_doc_dependencies) | |
6 | set(doc_depends pldoc ltx2htm archive) | |
7 | set(missing) | |
8 | ||
9 | foreach(pkg ${doc_depends}) | |
10 | has_package(${pkg} has_pkg) | |
11 | if(NOT has_pkg) | |
12 | set(missing "${missing} ${pkg}") | |
13 | list(APPEND SWIPL_PACKAGE_LIST ${pkg}) | |
14 | endif() | |
15 | endforeach() | |
16 | ||
17 | if(missing) | |
18 | set(INSTALL_DOCUMENTATION OFF CACHE BOOL "Install the HTML documentation files" FORCE) | |
19 | set(WARN_NO_DOCUMENTATION ON CACHE BOOL "Re-check documentation" FORCE) | |
20 | message( | |
21 | "WARNING: Dropped building the documentation because the following \ | |
22 | packages are missing: ${missing}") | |
23 | else() | |
24 | set(INSTALL_DOCUMENTATION ON CACHE BOOL "Install the HTML documentation files" FORCE) | |
25 | set(WARN_NO_DOCUMENTATION OFF CACHE BOOL "Re-check documentation" FORCE) | |
26 | endif() | |
27 | endfunction() | |
28 | ||
29 | check_doc_dependencies() | |
30 | ||
31 | endif() |
343 | 343 | clpr_dual_linsum(Coeff, Name, Coeff*Name). |
344 | 344 | |
345 | 345 | clpr_constraint_coefficient(c(_, Left, _, _), Coeff) :- |
346 | maplist(coeff_, Left, Coeff). | |
346 | maplist(all_coeffs, Left, Coeff). | |
347 | 347 | |
348 | 348 | all_coeffs(Coeff*_, Coeff). |
349 | 349 |
80 | 80 | |
81 | 81 | %% environ(?Name, ?Value) is nondet. |
82 | 82 | % |
83 | % True if Value an atom associated with the environment variable | |
84 | % Name. | |
85 | % | |
86 | % @tbd Mode -Name is not supported | |
83 | % True if Value is an atom associated with the environment variable | |
84 | % or system property Name. | |
85 | % | |
86 | % @tbd Mode -Name is not supported. | |
87 | % | |
88 | % Because SWI-Prolog doesn't have an obvious equivalent to | |
89 | % SICStus system properties, this predicate currently | |
90 | % behaves as if no system properties are defined, | |
91 | % i. e. only environment variables are returned. | |
92 | % | |
93 | % @compat sicstus | |
87 | 94 | |
88 | 95 | environ(Name, Value) :- |
89 | 96 | getenv(Name, Value). |
43 | 43 | %% term_variables_bag(+Term, -Variables) is det. |
44 | 44 | % |
45 | 45 | % Variables is a list of variables that appear in Term. The |
46 | % variables are ordered according to depth-first lef-right walking | |
46 | % variables are ordered according to depth-first left-right walking | |
47 | 47 | % of the term. Variables contains no duplicates. This is the same |
48 | % as SWI-Prolog's term_variables. | |
48 | % as SWI-Prolog's term_variables/2. | |
49 | 49 | |
50 | 50 | term_variables_bag(Term, Variables) :- |
51 | 51 | term_variables(Term, Variables). |
51 | 51 | git_show/4, % +Dir, +Hash, -Commit, +Options |
52 | 52 | git_commit_data/3 % +Field, +Record, -Value |
53 | 53 | ]). |
54 | :- use_module(library(record),[record/1,current_record/2, op(_,_,record)]). | |
54 | :- use_module(library(record),[(record)/1,current_record/2, op(_,_,record)]). | |
55 | 55 | |
56 | 56 | :- autoload(library(apply),[maplist/3]). |
57 | 57 | :- autoload(library(error),[must_be/2,existence_error/2]). |
308 | 308 | directory(Directory) |
309 | 309 | ]), |
310 | 310 | Status == exit(0), |
311 | string_codes(".\n", Codes). | |
311 | string_codes(GitDir0, Codes), | |
312 | split_string(GitDir0, "", " \n", [GitDir]), | |
313 | sub_string(GitDir, B, _, A, "/.git/modules/"), | |
314 | !, | |
315 | sub_string(GitDir, 0, B, _, Main), | |
316 | sub_string(GitDir, _, A, 0, Below), | |
317 | directory_file_path(Main, Below, Dir), | |
318 | same_file(Dir, Directory). | |
312 | 319 | |
313 | 320 | %! git_describe(-Version, +Options) is semidet. |
314 | 321 | % |
385 | 385 | option(right_margin(RM), Options), |
386 | 386 | Indent + Width < RM % fits on a line, simply write |
387 | 387 | -> pprint(Term, Ctx, Options) |
388 | ; Term =.. [Name|Args], | |
388 | ; compound_name_arguments(Term, Name, Args), | |
389 | 389 | format(atom(Buf2), '~q(', [Name]), |
390 | 390 | write(Out, Buf2), |
391 | 391 | atom_length(Buf2, FunctorIndent), |
438 | 438 | ). |
439 | 439 | |
440 | 440 | |
441 | pp_compound_args([], _, _). | |
441 | 442 | pp_compound_args([H|T], Ctx, Options) :- |
442 | 443 | pp(H, Ctx, Options), |
443 | 444 | ( T == [] |
570 | 570 | '$get_predicate_attribute'(Module:Head, defined, 1). |
571 | 571 | walk_called(ClosureCall, _, _, _) :- |
572 | 572 | compound(ClosureCall), |
573 | functor(ClosureCall, Closure, _), | |
573 | compound_name_arity(ClosureCall, Closure, _), | |
574 | 574 | blob(Closure, closure), |
575 | 575 | !, |
576 | 576 | '$closure_predicate'(Closure, Module:Name/Arity), |
1045 | 1045 | |
1046 | 1046 | |
1047 | 1047 | hidden_predicate(Name, _) :- |
1048 | atom(Name), % []/N is not hidden | |
1048 | 1049 | sub_atom(Name, 0, _, _, '$wrap$'). |
1049 | 1050 | |
1050 | 1051 |
1786 | 1786 | var_or_nonneg(X) :- integer(X), X >= 0, !. |
1787 | 1787 | |
1788 | 1788 | pi_to_term(Name/Arity, Term) :- |
1789 | atom(Name), integer(Arity), Arity >= 0, | |
1789 | (atom(Name)->true;Name==[]), integer(Arity), Arity >= 0, | |
1790 | 1790 | !, |
1791 | 1791 | functor(Term, Name, Arity). |
1792 | 1792 | pi_to_term(Name//Arity0, Term) :- |
41 | 41 | :- autoload(library(apply),[maplist/3]). |
42 | 42 | :- autoload(library(lists),[append/3,member/2,subtract/3]). |
43 | 43 | :- autoload(library(make),[make/0]). |
44 | :- autoload(library(pldoc/man_index), [save_man_index/0]). | |
44 | 45 | |
45 | 46 | |
46 | 47 | /** <module> Installation support predicates |
148 | 149 | % Create swi('doc/manindex.db') during the build process. |
149 | 150 | |
150 | 151 | cmake_save_man_index :- |
151 | use_module(library(pldoc/man_index)), | |
152 | 152 | save_man_index. |
153 | 153 | |
154 | 154 |
512 | 512 | safe_primitive(compound(_)). |
513 | 513 | safe_primitive(callable(_)). |
514 | 514 | safe_primitive(ground(_)). |
515 | safe_primitive(system:nonground(_,_)). | |
515 | 516 | safe_primitive(system:cyclic_term(_)). |
516 | 517 | safe_primitive(acyclic_term(_)). |
517 | 518 | safe_primitive(system:is_stream(_)). |
77 | 77 | \secref{metapred} for mode flags to label meta-predicate arguments in |
78 | 78 | module export declarations. |
79 | 79 | |
80 | \subsection{Redicate indicators} \label{sec:predicate_indic} | |
80 | \subsection{Predicate indicators} \label{sec:predicate-indic} | |
81 | 81 | |
82 | 82 | \index{predicate indicator}% |
83 | 83 | Referring to a predicate in running text is done using a |
86 | 86 | generally omitted if it is irrelevant (case of a built-in predicate) or if it |
87 | 87 | can be inferred from context. |
88 | 88 | |
89 | \subsubsection{Non-terminal indicatora} \label{sec:nonterminal_indic} | |
89 | \subsubsection{Non-terminal indicators} \label{sec:nonterminal-indic} | |
90 | 90 | |
91 | 91 | \index{non-terminal indicator}% |
92 | 92 | Compliant to the ISO standard draft on Definite Clause Grammars (see |
791 | 791 | constraint symbol. |
792 | 792 | \end{itemlist} |
793 | 793 | |
794 | \section{CHR Compiler Errors and Warnings} \label{sec:chr-errors} | |
794 | \section{CHR Compiler Errors and Warnings} \label{sec:chr-warnings-and-errors} | |
795 | 795 | %================== |
796 | 796 | |
797 | 797 | In this section we summarize the most important error and warning messages |
14 | 14 | |
15 | 15 | Most implementations of the Prolog language are designed to serve a |
16 | 16 | limited set of use cases. SWI-Prolog is no exception to this rule. |
17 | SWI-Prolog positions itself primarily as a Prolog environment for | |
17 | SWI-Prolog positions itself primarily as a Prolog environment for | |
18 | 18 | `programming in the large' and use cases where it plays a central role |
19 | 19 | in an application, i.e., where it acts as `glue' between components. At |
20 | 20 | the same time, SWI-Prolog aims at providing a productive rapid |
24 | 24 | and interfaces to a large number of document formats, protocols and |
25 | 25 | programming languages. Prototyping is facilitated by good development |
26 | 26 | tools, both for command line usage and for usage with graphical |
27 | development tools. Demand loading of predicates from the library and a | |
27 | development tools. Demand loading of predicates from the library and a | |
28 | 28 | `make' facility avoids the \emph{requirement} for using declarations and |
29 | 29 | reduces typing. |
30 | 30 | |
35 | 35 | Note that these positions do not imply that the system cannot be used |
36 | 36 | with other scenarios. SWI-Prolog is used as an embedded language where |
37 | 37 | it serves as a small rule subsystem in a large application. It is also |
38 | used as a deductive database. In some cases this is the right choice | |
38 | used as a deductive database. In some cases, this is the right choice | |
39 | 39 | because SWI-Prolog has features that are required in the application, |
40 | such as threading or Unicode support. In general though, for example, | |
40 | such as threading or Unicode support. In general though, for example: | |
41 | 41 | GNU-Prolog is more suited for embedding because it is small and can |
42 | compile to native code, XSB is better for deductive databases because it | |
42 | compile to native code; XSB is better for deductive databases because it | |
43 | 43 | provides a mature implementation of \jargon{tabling} including support |
44 | 44 | for incremental updates and \jargon{Well Founded |
45 | 45 | Semantics}\footnote{Sponsored by Kyndi and with help from the XSB |
46 | 46 | developers Theresa Swift and David S. Warren, SWI-Prolog now supports |
47 | many of the XSB features.}, and ECLiPSe is better at constraint | |
47 | many of the XSB features.}; and ECLiPSe is better at constraint | |
48 | 48 | handling. |
49 | 49 | |
50 | 50 | The syntax and set of built-in predicates is based on the ISO standard |
53 | 53 | The infrastructure for constraint programming is based on hProlog |
54 | 54 | \cite{Demoen:CW350}. Some libraries are copied from the |
55 | 55 | YAP\footnote{\url{http://www.dcc.fc.up.pt/\~{}vsc/Yap/}} system. |
56 | Together with YAP we developed a portability framework (see | |
56 | Together with YAP, we developed a portability framework (see | |
57 | 57 | \secref{dialect}). This framework has been filled for SICStus Prolog, |
58 | 58 | YAP, IF/Prolog and Ciao. SWI-Prolog version~7 introduces various |
59 | 59 | extensions to the Prolog language (see \secref{extensions}). The |
74 | 74 | than one million lines of Prolog code. |
75 | 75 | |
76 | 76 | SWI-Prolog has two development tracks. \emph{Stable} releases have an |
77 | even \emph{minor} version number (e.g., 6.2.1) and are released as a | |
77 | even \emph{minor} version number (e.g., 6.2.1) and are released as a | |
78 | 78 | branch from the development version when the development |
79 | 79 | version is considered stable and there is sufficient new functionality |
80 | 80 | to justify a stable release. Stable releases often get a few patch |
102 | 102 | Users requiring more support should ensure access to knowledgeable developers. |
103 | 103 | |
104 | 104 | \item [Performance is your first concern] |
105 | Various free and commercial systems have better performance. But, | |
105 | Various free and commercial systems have better performance. But, | |
106 | 106 | `standard' Prolog benchmarks disregard many factors that are often |
107 | 107 | critical to the performance of large applications. SWI-Prolog is not |
108 | 108 | good at fast calling of simple predicates, but it is fast with dynamic |
210 | 210 | |
211 | 211 | SWI-Prolog started back in 1986 with the requirement for a Prolog that |
212 | 212 | could handle recursive interaction with the C-language: Prolog calling C |
213 | and C calling Prolog recursively. In those days Prolog systems were not | |
213 | and C calling Prolog recursively. In those days, Prolog systems were not | |
214 | 214 | very aware of their environment and we needed such a system to support |
215 | 215 | interactive applications. Since then, SWI-Prolog's development has been |
216 | guided by requests from the user community, especially focussing on (in | |
216 | guided by requests from the user community, especially focusing on (in | |
217 | 217 | arbitrary order) interaction with the environment, scalability, (I/O) |
218 | 218 | performance, standard compliance, teaching and the program development |
219 | 219 | environment. |
58 | 58 | |
59 | 59 | \newcommand{\vmajor}{8} |
60 | 60 | \newcommand{\vminor}{2} |
61 | \newcommand{\vpatch}{3} | |
61 | \newcommand{\vpatch}{4} | |
62 | 62 | \newcommand{\vtag}{} |
63 | \newcommand{\vmonth}{November} | |
64 | \newcommand{\vyear}{2020} | |
63 | \newcommand{\vmonth}{January} | |
64 | \newcommand{\vyear}{2021} | |
65 | 65 | |
66 | 66 | #ifdef BOOK |
67 | 67 | \newcommand{\versionshort}{\vmajor} |
1390 | 1390 | \end{itemize} |
1391 | 1391 | |
1392 | 1392 | \prologflagitem{compile_meta_arguments}{atom}{rw} |
1393 | Experimental flag that controls compilation of arguments passed to | |
1394 | meta-calls marked `0' or `\chr{^}' (see meta_predicate/1). Supported | |
1395 | values are: | |
1393 | This flag controls compilation of arguments passed to meta-calls marked | |
1394 | `0' or `\chr{^}' (see meta_predicate/1). Supported values are: | |
1396 | 1395 | |
1397 | 1396 | \begin{description} |
1398 | 1397 | \termitem{false}{} |
1399 | (default). Meta-arguments are passed verbatim. | |
1398 | (default). Meta-arguments are passed verbatim. If the argument is a | |
1399 | control structure ((A,B), (A;B), (A->B;C), etc.) it is compile to an | |
1400 | temporary clause allocated on the environment stack when the | |
1401 | meta-predicate is called. | |
1402 | ||
1400 | 1403 | \termitem{control}{} |
1401 | Compile meta-arguments that contain control structures ((A,B), (A;B), | |
1402 | (A->B;C), etc.). If not compiled at compile time, such arguments are | |
1403 | compiled to a temporary clause before execution. Using this option | |
1404 | enhances performance of processing complex meta-goals that are known | |
1405 | at compile time. | |
1406 | \termitem{true}{} | |
1407 | Also compile references to normal user predicates. This harms | |
1408 | performance (a little), but enhances the power of poor-mens consistency | |
1409 | check used by make/0 and implemented by list_undefined/0. | |
1404 | Compile meta-arguments that contain control structures to an auxiliary | |
1405 | predicate. This generally improves performance as well as the debugging | |
1406 | experience. | |
1407 | ||
1410 | 1408 | \termitem{always}{} |
1411 | Always create an intermediate clause, even for system predicates. This | |
1412 | prepares for replacing the normal head of the generated predicate with | |
1413 | a special reference (similar to database references as used by, e.g., | |
1414 | assert/2) that provides direct access to the executable code, thus | |
1415 | avoiding runtime lookup of predicates for meta-calling. | |
1409 | Always create an intermediate clause, even for system | |
1410 | predicates.\footnote{This may be used in the future for | |
1411 | replacing the normal head of the generated predicate with a special | |
1412 | reference (similar to database references as used by, e.g., assert/2) | |
1413 | that provides direct access to the executable code, thus avoiding | |
1414 | runtime lookup of predicates for meta-calling.} | |
1416 | 1415 | \end{description} |
1417 | 1416 | |
1418 | 1417 | \prologflagitem{compiled_at}{atom}{r} |
3406 | 3405 | |
3407 | 3406 | \begin{table} |
3408 | 3407 | \begin{center} |
3409 | \begin{tabular}{|c|l|p{5cm}|} | |
3408 | \begin{tabular}{|l|p{5cm}|} | |
3410 | 3409 | \hline |
3411 | Option & Area name & Description \\ | |
3410 | Area name & Description \\ | |
3412 | 3411 | \hline |
3413 | \cmdlineoption{-L} & \bf local stack & The local stack is used to store | |
3412 | \bf local stack & The local stack is used to store | |
3414 | 3413 | the execution environments of procedure |
3415 | 3414 | invocations. The space for an environment is |
3416 | 3415 | reclaimed when it fails, exits without leaving |
3418 | 3417 | the !/0 predicate or no choice points have |
3419 | 3418 | been created since the invocation and the last |
3420 | 3419 | subclause is started (last call optimisation). \\ |
3421 | \cmdlineoption{-G} & \bf global stack & The global stack is used | |
3420 | \bf global stack & The global stack is used | |
3422 | 3421 | to store terms created during Prolog's |
3423 | 3422 | execution. Terms on this stack will be reclaimed |
3424 | 3423 | by backtracking to a point before the term |
3425 | 3424 | was created or by garbage collection (provided the |
3426 | 3425 | term is no longer referenced). \\ |
3427 | \cmdlineoption{-T} & \bf trail stack & The trail stack is used to store | |
3426 | \bf trail stack & The trail stack is used to store | |
3428 | 3427 | assignments during execution. Entries on this |
3429 | 3428 | stack remain alive until backtracking before the |
3430 | 3429 | point of creation or the garbage collector |
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-2020, University of Amsterdam | |
5 | Copyright (c) 2000-2021, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | CWI, Amsterdam |
8 | SWI-Prolog Solutions b.v. | |
8 | 9 | All rights reserved. |
9 | 10 | |
10 | 11 | Redistribution and use in source and binary forms, with or without |
90 | 91 | static atom_t ATOM_timeout; |
91 | 92 | static atom_t ATOM_release; |
92 | 93 | static atom_t ATOM_infinite; |
94 | static atom_t ATOM_text; | |
95 | static atom_t ATOM_binary; | |
96 | static atom_t ATOM_octet; | |
97 | static atom_t ATOM_utf8; | |
98 | static atom_t ATOM_ascii; | |
99 | static atom_t ATOM_iso_latin_1; | |
100 | static atom_t ATOM_unicode_be; | |
101 | static atom_t ATOM_unicode_le; | |
102 | ||
93 | 103 | static functor_t FUNCTOR_error2; |
94 | 104 | static functor_t FUNCTOR_process_error2; |
95 | 105 | static functor_t FUNCTOR_system_error2; |
96 | 106 | static functor_t FUNCTOR_pipe1; |
107 | static functor_t FUNCTOR_pipe2; | |
97 | 108 | static functor_t FUNCTOR_stream1; |
98 | 109 | static functor_t FUNCTOR_exit1; |
99 | 110 | static functor_t FUNCTOR_killed1; |
100 | 111 | static functor_t FUNCTOR_eq2; /* =/2 */ |
112 | static functor_t FUNCTOR_type1; | |
113 | static functor_t FUNCTOR_encoding1; | |
101 | 114 | |
102 | 115 | #define MAYBE 2 |
103 | 116 | |
149 | 162 | typedef struct p_stream |
150 | 163 | { term_t term; /* P in pipe(P) */ |
151 | 164 | std_type type; /* type of stream */ |
165 | IOENC encoding; /* Encoding for the stream */ | |
152 | 166 | #ifdef __WINDOWS__ |
153 | 167 | HANDLE fd[2]; /* pipe handles */ |
154 | 168 | #else |
279 | 293 | |
280 | 294 | #ifndef __WINDOWS__ |
281 | 295 | static int |
282 | already_in_env(const char *env, const char *e) | |
283 | { for(; *env; env += strlen(env)+1) | |
296 | already_in_env(const char *env, int count, const char *e) | |
297 | { for(; count-- > 0; env += strlen(env)+1) | |
284 | 298 | { const char *s, *q; |
285 | 299 | |
286 | 300 | for(s=env, q=e; *s && *q && *s == *q && *s != '=' && *q != '='; s++,q++) |
332 | 346 | if ( !PL_get_nil_ex(tail) ) |
333 | 347 | return FALSE; |
334 | 348 | |
349 | if ( pass && count == 0 ) | |
350 | return TRUE; /* environment([]) is a no-op */ | |
351 | ||
335 | 352 | #ifndef __WINDOWS__ |
336 | 353 | if ( pass ) |
337 | 354 | { |
341 | 358 | extern char **environ; |
342 | 359 | #endif |
343 | 360 | char **e; |
361 | int count0 = count; | |
344 | 362 | |
345 | 363 | for(e=environ; e && *e; e++) |
346 | { if ( !already_in_env(eb->buffer, *e) ) | |
364 | { if ( !already_in_env(eb->buffer, count0, *e) ) | |
347 | 365 | { add_ecbuf(eb, *e, strlen(*e)); |
348 | 366 | add_ecbuf(eb, ECHARS("\0"), 1); |
349 | 367 | count++; |
366 | 384 | #endif |
367 | 385 | |
368 | 386 | return TRUE; |
387 | } | |
388 | ||
389 | ||
390 | static int | |
391 | get_type(term_t head, IOENC *enc) | |
392 | { atom_t a; | |
393 | ||
394 | if ( PL_get_atom_ex(head, &a) ) | |
395 | { if ( a == ATOM_text ) | |
396 | *enc = ENC_ANSI; | |
397 | else if ( a == ATOM_binary ) | |
398 | *enc = ENC_OCTET; | |
399 | else | |
400 | return PL_domain_error("stream_type", head); | |
401 | ||
402 | return TRUE; | |
403 | } | |
404 | ||
405 | return FALSE; | |
406 | } | |
407 | ||
408 | /* TBD: provide a public API for translating encoding names to | |
409 | * the IOENC enum | |
410 | */ | |
411 | ||
412 | static int | |
413 | get_encoding(term_t head, IOENC *enc) | |
414 | { atom_t a; | |
415 | ||
416 | if ( PL_get_atom_ex(head, &a) ) | |
417 | { if ( a == ATOM_octet ) | |
418 | *enc = ENC_OCTET; | |
419 | else if ( a == ATOM_ascii ) | |
420 | *enc = ENC_ASCII; | |
421 | else if ( a == ATOM_iso_latin_1 ) | |
422 | *enc = ENC_ISO_LATIN_1; | |
423 | else if ( a == ATOM_text ) | |
424 | *enc = ENC_ANSI; | |
425 | else if ( a == ATOM_utf8 ) | |
426 | *enc = ENC_UTF8; | |
427 | else if ( a == ATOM_unicode_be ) | |
428 | *enc = ENC_UNICODE_BE; | |
429 | else if ( a == ATOM_unicode_le ) | |
430 | *enc = ENC_UNICODE_LE; | |
431 | else | |
432 | return PL_domain_error("encoding", head); | |
433 | ||
434 | return TRUE; | |
435 | } | |
436 | ||
437 | return FALSE; | |
369 | 438 | } |
370 | 439 | |
371 | 440 | |
383 | 452 | } else |
384 | 453 | { return PL_domain_error("process_stream", t); |
385 | 454 | } |
386 | } else if ( PL_is_functor(t, FUNCTOR_pipe1) ) | |
455 | } else if ( PL_is_functor(t, FUNCTOR_pipe1) || | |
456 | PL_is_functor(t, FUNCTOR_pipe2) ) | |
387 | 457 | { stream->term = PL_new_term_ref(); |
458 | stream->encoding = ENC_ANSI; | |
388 | 459 | _PL_get_arg(1, t, stream->term); |
389 | 460 | if ( !PL_is_variable(stream->term) ) |
390 | 461 | { for (i = 0; i < info->pipes; i++) |
393 | 464 | } |
394 | 465 | if (i == info->pipes) |
395 | 466 | return PL_uninstantiation_error(stream->term); |
467 | } | |
468 | if ( PL_is_functor(t, FUNCTOR_pipe2) ) | |
469 | { term_t tail = PL_new_term_ref(); | |
470 | term_t head = PL_new_term_ref(); | |
471 | ||
472 | _PL_get_arg(2, t, tail); | |
473 | while(PL_get_list_ex(tail, head, tail)) | |
474 | { if ( PL_is_functor(head, FUNCTOR_type1) ) | |
475 | { _PL_get_arg(1, head, head); | |
476 | if ( !get_type(head, &stream->encoding) ) | |
477 | return FALSE; | |
478 | } else if ( PL_is_functor(head, FUNCTOR_encoding1) ) | |
479 | { _PL_get_arg(1, head, head); | |
480 | if ( !get_encoding(head, &stream->encoding) ) | |
481 | return FALSE; | |
482 | } else | |
483 | return PL_domain_error("pipe_option", head); | |
484 | } | |
485 | if ( !PL_get_nil_ex(tail) ) | |
486 | return FALSE; | |
396 | 487 | } |
397 | 488 | stream->type = std_pipe; |
398 | 489 | info->pipes++; |
681 | 772 | |
682 | 773 | |
683 | 774 | static IOSTREAM * |
775 | open_process_pipe(process_context *pc, p_options *info, int which, int fdn) | |
776 | { void *handle; | |
684 | 777 | #ifdef __WINDOWS__ |
685 | open_process_pipe(process_context *pc, int which, HANDLE fd) | |
778 | HANDLE fd = info->streams[which].fd[fdn]; | |
686 | 779 | #else |
687 | open_process_pipe(process_context *pc, int which, int fd) | |
688 | #endif | |
689 | { void *handle; | |
690 | int flags; | |
780 | int fd = info->streams[which].fd[fdn]; | |
781 | #endif | |
782 | int flags = SIO_RECORDPOS|SIO_FBUF; | |
783 | IOSTREAM *s; | |
691 | 784 | |
692 | 785 | pc->open_mask |= (1<<which); |
693 | 786 | #ifdef __WINDOWS__ |
696 | 789 | pc->pipes[which] = fd; |
697 | 790 | #endif |
698 | 791 | |
699 | #define ISO_FLAGS (SIO_RECORDPOS|SIO_FBUF|SIO_TEXT) | |
792 | if ( info->streams[which].encoding != ENC_OCTET ) | |
793 | flags |= SIO_TEXT; | |
700 | 794 | |
701 | 795 | if ( which == 0 ) |
702 | flags = SIO_OUTPUT|ISO_FLAGS; | |
796 | flags |= SIO_OUTPUT; | |
703 | 797 | else |
704 | flags = SIO_INPUT|ISO_FLAGS; | |
798 | flags |= SIO_INPUT; | |
705 | 799 | |
706 | 800 | handle = (void *)((uintptr_t)pc | (uintptr_t)which); |
707 | 801 | |
708 | return Snew(handle, flags, &Sprocessfunctions); | |
802 | if ( (s=Snew(handle, flags, &Sprocessfunctions)) ) | |
803 | s->encoding = info->streams[which].encoding; | |
804 | ||
805 | return s; | |
709 | 806 | } |
710 | 807 | |
711 | 808 | |
1236 | 1333 | |
1237 | 1334 | if ( info->streams[0].type == std_pipe ) |
1238 | 1335 | { CloseHandle(info->streams[0].fd[0]); |
1239 | if ( (s = open_process_pipe(pc, 0, info->streams[0].fd[1])) ) | |
1336 | if ( (s = open_process_pipe(pc, info, 0, 1)) ) | |
1240 | 1337 | rc = PL_unify_stream(info->streams[0].term, s); |
1241 | 1338 | else |
1242 | 1339 | CloseHandle(info->streams[0].fd[1]); |
1243 | 1340 | } |
1244 | 1341 | if ( info->streams[1].type == std_pipe ) |
1245 | 1342 | { CloseHandle(info->streams[1].fd[1]); |
1246 | if ( rc && (s = open_process_pipe(pc, 1, info->streams[1].fd[0])) ) | |
1343 | if ( rc && (s = open_process_pipe(pc, info, 1, 0)) ) | |
1247 | 1344 | PL_unify_stream(info->streams[1].term, s); |
1248 | 1345 | else |
1249 | 1346 | CloseHandle(info->streams[1].fd[0]); |
1251 | 1348 | if ( info->streams[2].type == std_pipe && |
1252 | 1349 | ( !info->streams[1].term || PL_compare(info->streams[1].term, info->streams[2].term) != 0 ) ) |
1253 | 1350 | { CloseHandle(info->streams[2].fd[1]); |
1254 | if ( rc && (s = open_process_pipe(pc, 2, info->streams[2].fd[0])) ) | |
1351 | if ( rc && (s = open_process_pipe(pc, info, 2, 0)) ) | |
1255 | 1352 | rc = PL_unify_stream(info->streams[2].term, s); |
1256 | 1353 | else |
1257 | 1354 | CloseHandle(info->streams[2].fd[0]); |
1555 | 1652 | return rc; |
1556 | 1653 | } |
1557 | 1654 | |
1655 | static IOSTREAM * | |
1656 | p_fdopen(p_options *info, int which, int fdn, char *mode) | |
1657 | { IOSTREAM *s; | |
1658 | char m[10]; | |
1659 | char *mp = m; | |
1660 | ||
1661 | *mp++ = mode[0]; | |
1662 | if ( info->streams[which].encoding == ENC_OCTET ) | |
1663 | *mp++ = 'b'; | |
1664 | *mp = 0; | |
1665 | ||
1666 | if ( (s=Sfdopen(info->streams[which].fd[fdn], m)) ) | |
1667 | s->encoding = info->streams[which].encoding; | |
1668 | ||
1669 | return s; | |
1670 | } | |
1671 | ||
1558 | 1672 | |
1559 | 1673 | static int |
1560 | 1674 | process_parent_side(p_options *info, int pid) |
1573 | 1687 | |
1574 | 1688 | if ( info->streams[0].type == std_pipe ) |
1575 | 1689 | { close_ok(info->streams[0].fd[0]); |
1576 | if ( (s = open_process_pipe(pc, 0, info->streams[0].fd[1])) ) | |
1690 | if ( (s = open_process_pipe(pc, info, 0, 1)) ) | |
1577 | 1691 | rc = PL_unify_stream(info->streams[0].term, s); |
1578 | 1692 | else |
1579 | 1693 | close_ok(info->streams[0].fd[1]); |
1580 | 1694 | } |
1581 | 1695 | if ( info->streams[1].type == std_pipe ) |
1582 | 1696 | { close_ok(info->streams[1].fd[1]); |
1583 | if ( rc && (s = open_process_pipe(pc, 1, info->streams[1].fd[0])) ) | |
1697 | if ( rc && (s = open_process_pipe(pc, info, 1, 0)) ) | |
1584 | 1698 | rc = PL_unify_stream(info->streams[1].term, s); |
1585 | 1699 | else |
1586 | 1700 | close_ok(info->streams[1].fd[0]); |
1588 | 1702 | if ( info->streams[2].type == std_pipe && |
1589 | 1703 | ( !info->streams[1].term || PL_compare(info->streams[1].term, info->streams[2].term) != 0 ) ) |
1590 | 1704 | { close_ok(info->streams[2].fd[1]); |
1591 | if ( rc && (s = open_process_pipe(pc, 2, info->streams[2].fd[0])) ) | |
1705 | if ( rc && (s = open_process_pipe(pc, info, 2, 0)) ) | |
1592 | 1706 | rc = PL_unify_stream(info->streams[2].term, s); |
1593 | 1707 | else |
1594 | 1708 | close_ok(info->streams[2].fd[0]); |
1600 | 1714 | |
1601 | 1715 | if ( info->streams[0].type == std_pipe ) |
1602 | 1716 | { close_ok(info->streams[0].fd[0]); |
1603 | if ( (s = Sfdopen(info->streams[0].fd[1], "w")) ) | |
1717 | if ( (s = p_fdopen(info, 0, 1, "w")) ) | |
1604 | 1718 | rc = PL_unify_stream(info->streams[0].term, s); |
1605 | 1719 | else |
1606 | 1720 | close_ok(info->streams[0].fd[1]); |
1607 | 1721 | } |
1608 | 1722 | if ( info->streams[1].type == std_pipe ) |
1609 | 1723 | { close_ok(info->streams[1].fd[1]); |
1610 | if ( rc && (s = Sfdopen(info->streams[1].fd[0], "r")) ) | |
1724 | if ( rc && (s = p_fdopen(info, 1, 0, "r")) ) | |
1611 | 1725 | rc = PL_unify_stream(info->streams[1].term, s); |
1612 | 1726 | else |
1613 | 1727 | close_ok(info->streams[1].fd[0]); |
1615 | 1729 | if ( info->streams[2].type == std_pipe && |
1616 | 1730 | ( !info->streams[1].term || PL_compare(info->streams[1].term, info->streams[2].term) != 0 ) ) |
1617 | 1731 | { close_ok(info->streams[2].fd[1]); |
1618 | if ( rc && (s = Sfdopen(info->streams[2].fd[0], "r")) ) | |
1732 | if ( rc && (s = p_fdopen(info, 2, 0, "r")) ) | |
1619 | 1733 | PL_unify_stream(info->streams[2].term, s); |
1620 | 1734 | else |
1621 | 1735 | close_ok(info->streams[2].fd[0]); |
2141 | 2255 | MKATOM(timeout); |
2142 | 2256 | MKATOM(release); |
2143 | 2257 | MKATOM(infinite); |
2258 | MKATOM(text); | |
2259 | MKATOM(binary); | |
2260 | MKATOM(octet); | |
2261 | MKATOM(utf8); | |
2262 | MKATOM(ascii); | |
2263 | MKATOM(iso_latin_1); | |
2264 | MKATOM(unicode_be); | |
2265 | MKATOM(unicode_le); | |
2144 | 2266 | |
2145 | 2267 | MKFUNCTOR(pipe, 1); |
2268 | MKFUNCTOR(pipe, 2); | |
2269 | MKFUNCTOR(type, 1); | |
2270 | MKFUNCTOR(encoding, 1); | |
2146 | 2271 | MKFUNCTOR(stream, 1); |
2147 | 2272 | MKFUNCTOR(error, 2); |
2148 | 2273 | MKFUNCTOR(process_error, 2); |
94 | 94 | distinction. This implies that is_process/1 is incomplete and |
95 | 95 | unreliable. |
96 | 96 | |
97 | * SICStus only supports ISO 8859-1 (latin-1). This implementation | |
98 | supports arbitrary OS multibyte interaction using the default | |
99 | locale. | |
100 | ||
101 | 97 | * It is unclear what the detached(true) option is supposed to do. Disable |
102 | 98 | signals in the child? Use setsid() to detach from the session? The |
103 | 99 | current implementation uses setsid() on Unix systems. |
135 | 131 | % Bind the standard streams of the new process. Spec is one of |
136 | 132 | % the terms below. If pipe(Pipe) is used, the Prolog stream is |
137 | 133 | % a stream in text-mode using the encoding of the default |
138 | % locale. The encoding can be changed using set_stream/2. | |
134 | % locale. The encoding can be changed using set_stream/2, | |
135 | % or by using the two-argument form of =pipe=, which accepts an | |
136 | % encoding(Encoding) option. | |
139 | 137 | % The options =stdout= and =stderr= may use the same stream, |
140 | 138 | % in which case both output streams are connected to the same |
141 | 139 | % Prolog stream. |
149 | 147 | % Bind to a _null_ stream. Reading from such a stream |
150 | 148 | % returns end-of-file, writing produces no output |
151 | 149 | % * pipe(-Stream) |
150 | % * pipe(-Stream, +StreamOptions) | |
152 | 151 | % Attach input and/or output to a Prolog stream. |
152 | % The optional StreamOptions argument is a list of options | |
153 | % that affect the stream. Currently only the options | |
154 | % type(+Type) and encoding(+Encoding) are supported, | |
155 | % which have the same meaning as the stream properties | |
156 | % of the same name (see stream_property/2). | |
157 | % StreamOptions is provided mainly for SICStus compatibility - | |
158 | % the SWI-Prolog predicate set_stream/2 can be used | |
159 | % for the same purpose. | |
153 | 160 | % * stream(+Stream) |
154 | 161 | % Attach input or output to an existing Prolog stream. |
155 | 162 | % This stream must be associated with an OS file |
478 | 478 | status_has_content(created(_Location)). |
479 | 479 | status_has_content(moved(_To)). |
480 | 480 | status_has_content(moved_temporary(_To)). |
481 | status_has_content(gone(_URL)). | |
481 | 482 | status_has_content(see_other(_To)). |
482 | 483 | status_has_content(bad_request(_ErrorTerm)). |
483 | 484 | status_has_content(authorise(_Method)). |
584 | 585 | [ h1('Moved Temporary'), |
585 | 586 | p(['The document is currently ', |
586 | 587 | a(href(To), ' Here') |
588 | ]), | |
589 | \address | |
590 | ]), | |
591 | HTML). | |
592 | status_page_hook(gone(URL), html_tokens(HTML), _Options) :- | |
593 | phrase(page([ title('410 Resource Gone') | |
594 | ], | |
595 | [ h1('Resource Gone'), | |
596 | p(['The document has been removed ', | |
597 | a(href(URL), ' from here') | |
587 | 598 | ]), |
588 | 599 | \address |
589 | 600 | ]), |
1315 | 1326 | [ location(To) ]). |
1316 | 1327 | status_reply_headers(moved_temporary(To, Body), Body, |
1317 | 1328 | [ location(To) ]). |
1329 | status_reply_headers(gone(_URL, Body), Body, []). | |
1318 | 1330 | status_reply_headers(see_other(To, Body), Body, |
1319 | 1331 | [ location(To) ]). |
1320 | 1332 | status_reply_headers(authorise(Method, Body), Body, |
2436 | 2448 | { atom_codes(Value, Chars) |
2437 | 2449 | }. |
2438 | 2450 | |
2451 | chars_to_semicolon_or_blank([]), ";" --> | |
2452 | ";", | |
2453 | !. | |
2454 | chars_to_semicolon_or_blank([]) --> | |
2455 | " ", | |
2456 | blanks, | |
2457 | eos, | |
2458 | !. | |
2439 | 2459 | chars_to_semicolon_or_blank([H|T]) --> |
2440 | 2460 | [H], |
2441 | { H \== 32, H \== 0'; }, | |
2442 | 2461 | !, |
2443 | 2462 | chars_to_semicolon_or_blank(T). |
2444 | 2463 | chars_to_semicolon_or_blank([]) --> |
638 | 638 | ; domain_error(method, M) |
639 | 639 | ). |
640 | 640 | |
641 | %! map_method(+MethodID, -Method) | |
642 | % | |
643 | % Support additional ``METHOD`` keywords. Default are the official | |
644 | % HTTP methods as defined by the various RFCs. | |
645 | ||
646 | :- multifile | |
647 | map_method/2. | |
648 | ||
641 | 649 | map_method(delete, 'DELETE'). |
642 | 650 | map_method(get, 'GET'). |
643 | 651 | map_method(head, 'HEAD'). |
83 | 83 | a websocket inside the HTTP server infrastructure and |
84 | 84 | http_open_websocket/3 as a layer over http_open/3 to realise a client |
85 | 85 | connection. After establishing a connection, ws_send/2 and ws_receive/2 |
86 | can be used to send and receive messages. The predicate ws_close/2 is | |
86 | can be used to send and receive messages. The predicate ws_close/3 is | |
87 | 87 | provided to perform the closing handshake and dispose of the stream |
88 | 88 | objects. |
89 | 89 |
28 | 28 | if(PROG_JAVA_HOME) |
29 | 29 | message("-- Find Java home using ${PROG_JAVA_HOME}") |
30 | 30 | |
31 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) | |
32 | set(jdatamodel -d64) | |
33 | else() | |
34 | set(jdatamodel -d32) | |
31 | if(NOT APPLE) | |
32 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) | |
33 | set(jdatamodel -d64) | |
34 | else() | |
35 | set(jdatamodel -d32) | |
36 | endif() | |
35 | 37 | endif() |
36 | 38 | |
37 | 39 | exec_program(${PROG_JAVA_HOME} ARGS ${jdatamodel} |
38 | 40 | OUTPUT_VARIABLE jhome |
41 | OUTPUT_STRIP_TRAILING_WHITESPACE | |
39 | 42 | RETURN_VALUE jhome_ret) |
40 | 43 | if(jhome_ret EQUAL 0) |
41 | 44 | set(JAVA_HOME ${jhome} CACHE FILEPATH "Home of Java") |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2002-2018, University of Amsterdam, | |
5 | Copyright (c) 2002-2020, University of Amsterdam, | |
6 | 6 | VU University Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
56 | 56 | #include <sqlext.h> |
57 | 57 | #include <time.h> |
58 | 58 | #include <limits.h> /* LONG_MAX, etc. */ |
59 | #include <math.h> | |
59 | 60 | |
60 | 61 | #ifndef HAVE_SQLLEN |
61 | 62 | #define SQLLEN DWORD |
3420 | 3421 | |
3421 | 3422 | return TRUE; |
3422 | 3423 | #if defined(HAVE_LOCALTIME) || defined(HAVE_GMTIME) |
3423 | } else if ( PL_get_float(t, &tf) && tf <= LONG_MAX && tf >= LONG_MIN ) | |
3424 | } else if ( PL_get_float(t, &tf) ) | |
3424 | 3425 | { time_t t = (time_t)tf; |
3425 | 3426 | long ns = (long)((tf - (double)t) * 1000000000.0); |
3426 | 3427 | #if defined(HAVE_GMTIME) && defined USE_UTC |
3428 | 3429 | #else |
3429 | 3430 | struct tm *tm = localtime(&t); |
3430 | 3431 | #endif |
3432 | ||
3433 | if ( fabs(tf - (double)t) > 1.0 ) | |
3434 | return FALSE; /* out of range */ | |
3431 | 3435 | |
3432 | 3436 | stamp->year = tm->tm_year + 1900; |
3433 | 3437 | stamp->month = tm->tm_mon + 1; |
42 | 42 | print_html_head/1, % +Stream |
43 | 43 | predref//1, % +PI // |
44 | 44 | predref//2, % +PI, Options // |
45 | nopredref//1, % +PI // | |
45 | 46 | module_info/3, % +File, +Options0, -Options |
46 | 47 | doc_hide_private/3, % +Doc0, -Doc, +Options |
47 | 48 | edit_button//2, % +File, +Options, // |
70 | 71 | tags//1, % +Tags, // |
71 | 72 | term//3, % +Text, +Term, +Bindings, // |
72 | 73 | file_header//2, % +File, +Options, // |
74 | flagref//1, % +Flag | |
73 | 75 | objects//2, % +Objects, +Options, // |
74 | 76 | object_ref//2, % +Object, +Options, // |
75 | 77 | object_name//2, % +Object, +Object |
78 | 80 | object_page//2, % +Object, +Options, // |
79 | 81 | object_page_header//2, % +File, +Options, // |
80 | 82 | object_synopsis//2, % +Object, +Options, // |
81 | object_page_footer//2 % +Object, +Options, // | |
83 | object_footer//2, % +Object, +Options, // | |
84 | object_page_footer//2, % +Object, +Options, // | |
85 | cite//1 % +Citations | |
82 | 86 | ]). |
83 | 87 | :- use_module(library(lists)). |
84 | 88 | :- use_module(library(option)). |
1019 | 1023 | html([ div(a(href(location_by_id(pldoc_doc)+File), File)) |
1020 | 1024 | ]). |
1021 | 1025 | |
1026 | %! object_footer(+Obj, +Options)// is det. | |
1027 | % | |
1028 | % Call the hook prolog:doc_object_footer//2. This hook will be used to | |
1029 | % deal with examples. | |
1030 | ||
1031 | object_footer(Obj, Options) --> | |
1032 | prolog:doc_object_footer(Obj, Options), | |
1033 | !. | |
1034 | object_footer(_, _) --> []. | |
1035 | ||
1036 | ||
1022 | 1037 | %! object_page_footer(+Obj, +Options)// is det. |
1023 | 1038 | % |
1024 | 1039 | % Call the hook prolog:doc_object_page_footer//2. This hook will |
1025 | 1040 | % be used to deal with annotations. |
1026 | 1041 | |
1027 | 1042 | object_page_footer(Obj, Options) --> |
1028 | prolog:doc_object_page_footer(Obj, Options). | |
1043 | prolog:doc_object_page_footer(Obj, Options), | |
1044 | !. | |
1029 | 1045 | object_page_footer(_, _) --> []. |
1030 | 1046 | |
1031 | 1047 |
112 | 112 | blocked('/swipl-lfr.pl'). |
113 | 113 | blocked('/dcg_basics.pl'). % deprecated file |
114 | 114 | blocked('/readline.pl'). % conflicts with editline.pl |
115 | blocked('/win_menu.pl'). % Leads to warnings without a console. |
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 | CWI, Amsterdam |
8 | 8 | All rights reserved. |
45 | 45 | |
46 | 46 | :- autoload(doc_html, |
47 | 47 | [ object_tree/5, private/2, object_page_header/4, objects/4, |
48 | object_href/2, object_synopsis/4, object_page_footer/4, | |
48 | object_href/2, object_synopsis/4, object_footer/4, | |
49 | object_page_footer/4, | |
49 | 50 | object_ref/4, object_page/4, |
50 | 51 | object_source_button//2 |
51 | 52 | ]). |
53 | 54 | :- autoload(doc_search,[search_form/3]). |
54 | 55 | :- autoload(doc_util,[atom_to_object/2,atom_pi/2]). |
55 | 56 | :- autoload(man_index,[manual_object/5]). |
56 | :- autoload(library(apply),[maplist/2,maplist/3]). | |
57 | :- autoload(library(apply),[maplist/2,maplist/3,convlist/3]). | |
57 | 58 | :- autoload(library(debug),[assertion/1,debug/3]). |
58 | 59 | :- autoload(library(error),[permission_error/3,existence_error/2]). |
59 | 60 | :- autoload(library(filesex), |
752 | 753 | man_match(root, root, _) --> |
753 | 754 | !, |
754 | 755 | man_overview([]). |
755 | man_match((Parent+Path)-(Obj+[element(dt,A,C0)|DD]), Obj, Options) --> | |
756 | man_match((Parent+Path)-(Obj+DOM), Obj, Options) --> | |
756 | 757 | { \+ option(synopsis(false), Options), |
758 | DOM = [element(dt,A,C0)|DD], | |
759 | convlist(dt_obj, DOM, Objs), | |
757 | 760 | option(link_source(Link), Options, true), |
758 | 761 | man_qualified_object(Obj, Parent, LibOpt, QObj, Section), |
759 | 762 | !, |
765 | 768 | dom_list([ element(dt,[],[\man_synopsis(QObj, Section, LibOpt)]), |
766 | 769 | element(dt,A,C) |
767 | 770 | | DD |
768 | ], Path, Options). | |
771 | ], Path, Options), | |
772 | object_footer(Objs, Options). | |
769 | 773 | man_match((_Parent+Path)-(Obj+DOM), Obj, Options) --> |
770 | 774 | dom_list(DOM, Path, Options). |
771 | 775 | |
776 | dt_obj(element(dt,_,C), Obj) :- | |
777 | xpath(C, //a(@id=Atom), _), | |
778 | atom_to_object(Atom, Obj). | |
772 | 779 | |
773 | 780 | :- html_meta |
774 | 781 | dom_list(html, +, +, ?, ?). |
44 | 44 | prolog:doc_search_field//1, % +Options |
45 | 45 | prolog:doc_places_menu//1, % +Dir |
46 | 46 | prolog:doc_directory/1, % ?Dir |
47 | prolog:doc_object_footer//2, % +Object, +Options | |
47 | 48 | prolog:doc_object_page_footer//2, % +Object, +Options |
48 | 49 | prolog:doc_page_header//2, % +File, +Options |
49 | 50 | prolog:doc_links//2, % +Directory, +Options |
37 | 37 | |
38 | 38 | Version~2 of PlDoc extends the syntax with |
39 | 39 | \href{http://en.wikipedia.org/wiki/Markdown}{Markdown} markup as |
40 | specified by \href{http://www.stack.nl/~dimitri/doxygen/}{Docygen}. | |
40 | specified by \href{http://www.stack.nl/~dimitri/doxygen/}{Doxygen}. | |
41 | 41 | Based on experience with version~1, PlDoc~2 both tightens some rules |
42 | 42 | to avoid misinterpretations and relaxes others that were considered |
43 | 43 | too conservative. |
1070 | 1070 | that is widely accepted and not tied to a single system. In PlDoc~2, |
1071 | 1071 | we have adopted markdown, including many of the limitations and |
1072 | 1072 | extensions introduced by |
1073 | \href{http://www.stack.nl/~dimitri/doxygen/}{Docygen}. Limitations are | |
1073 | \href{http://www.stack.nl/~dimitri/doxygen/}{Doxygen}. Limitations are | |
1074 | 1074 | needed to avoid ambiguities due to the common use of symbol charaters |
1075 | 1075 | in programming languages. Extensions are desirable to make use of |
1076 | 1076 | already existing conventions and to support requirements of program |
4399 | 4399 | |
4400 | 4400 | if ( keep_gen == db->gc.last_gen ) |
4401 | 4401 | { garbage -= db->gc.uncollectable; |
4402 | assert((int64_t)garbage >= 0); | |
4402 | if ( (int64_t)garbage < 0 ) | |
4403 | garbage = 0; | |
4403 | 4404 | } |
4404 | 4405 | |
4405 | 4406 | return PL_unify_term(info, |
628 | 628 | test('Certificate is not issued by trusted CA'):- |
629 | 629 | do_verification_test(14, try_ssl_client('www.example.com', test_verify_hook), VerificationResults, Status), |
630 | 630 | ( VerificationResults:Status == [unknown_issuer]:true -> |
631 | % OpenSSL 1.0.2 and above | |
631 | % OpenSSL 1.0.2 - 1.1.1h | |
632 | 632 | true |
633 | 633 | ; VerificationResults:Status == [unknown_issuer, not_trusted]:true -> |
634 | 634 | % OpenSSL 1.0.1 and below |
635 | true | |
636 | ; VerificationResults:Status == [unknown_issuer, verified]:true -> | |
637 | % OpenSSL 1.1.1i and above | |
635 | 638 | true |
636 | 639 | ). |
637 | 640 |
35 | 35 | tipc_paxos_get/2, % ?Term, +Options |
36 | 36 | tipc_paxos_set/1, % ?Term |
37 | 37 | tipc_paxos_set/2, % ?Term, +Options |
38 | tipc_paxos_replicate/1, % ?Term | |
39 | 38 | tipc_paxos_on_change/2, % ?Term, +Goal |
40 | 39 | tipc_initialize/0 |
41 | 40 | ]). |
57 | 56 | %! tipc_paxos_get(?Term) is semidet. |
58 | 57 | %! tipc_paxos_get(?Term, +Options) is semidet. |
59 | 58 | %! tipc_paxos_set(?Term, +Options) is semidet. |
60 | %! tipc_paxos_replicate(?Term) is det. | |
61 | 59 | %! tipc_paxos_on_change(?Term, :Goal) is det. |
62 | 60 | |
63 | 61 | tipc_paxos_set(Term) :- paxos_set(Term, []). |
64 | 62 | tipc_paxos_set(Term, Options) :- paxos_set(Term, Options). |
65 | 63 | tipc_paxos_get(Term) :- paxos_get(Term, []). |
66 | 64 | tipc_paxos_get(Term, Options) :- paxos_get(Term, Options). |
67 | tipc_paxos_replicate(X) :- paxos_replicate(X). | |
68 | 65 | tipc_paxos_on_change(Term, Goal) :- paxos_on_change(Term, Goal). |
69 | 66 | |
70 | 67 | :- multifile |
199 | 199 | default_emacs_mode('.*\\.yaml~?$', yaml). |
200 | 200 | default_emacs_mode('.*\\.cmake~?$|CMakeLists.txt', cmake). |
201 | 201 | default_emacs_mode('.*\\.txt~?$', text). |
202 | default_emacs_mode('.*\\.md~?$', text). | |
203 | default_emacs_mode('.*\\.eml~?$', text). | |
202 | 204 | default_emacs_mode('[Cc]ompose|README|\\.article', text). |
203 | 205 | default_emacs_mode(Pattern, prolog) :- |
204 | 206 | user:prolog_file_type(Ext, prolog), |
0 | 0 | /* Part of XPCE --- The SWI-Prolog GUI toolkit |
1 | 1 | |
2 | 2 | Author: Jan Wielemaker and Anjo Anjewierden |
3 | E-mail: jan@swi.psy.uva.nl | |
4 | WWW: http://www.swi.psy.uva.nl/projects/xpce/ | |
5 | Copyright (c) 1985-2002, University of Amsterdam | |
3 | E-mail: jan@swi-prolog.org | |
4 | WWW: https://www.swi-prolog.org | |
5 | Copyright (c) 1985-2020, University of Amsterdam | |
6 | SWI-Prolog Solutions b.v. | |
6 | 7 | All rights reserved. |
7 | 8 | |
8 | 9 | Redistribution and use in source and binary forms, with or without |
34 | 35 | :- module(emacs_text_mode, []). |
35 | 36 | :- use_module(library(pce)). |
36 | 37 | |
37 | :- emacs_begin_mode(text, fundamental, | |
38 | "Edit plain text (sets fillmode", | |
38 | :- emacs_begin_mode(text, language, | |
39 | "Edit plain text (sets fillmode)", | |
39 | 40 | [], |
40 | []). | |
41 | [ '"' = string_quote('\\'), | |
42 | '''' = string_quote('\\'), | |
43 | '>' = comment_start, % use comment-region for quoting | |
44 | '\n' + comment_end | |
45 | ]). | |
41 | 46 | |
42 | 47 | setup_mode(E) :-> |
43 | 48 | "Switch editor into fill-mode":: |
84 | 84 | ]) :- |
85 | 85 | xsb_module_file(Module, File), |
86 | 86 | xsb_imports(Preds, File, Imports). |
87 | prolog_colour:goal_colours(dynamic(_Preds as Options), | |
88 | xsb-[ keyword(as)-[ predicates, | |
89 | OptColours | |
90 | ] | |
91 | ]) :- | |
92 | dyn_option_colours(Options, OptColours). | |
93 | 87 | |
94 | 88 | xsb_module_file(usermod, module(user)) :- |
95 | 89 | !. |
123 | 117 | xsb_imports(A, From, CA), |
124 | 118 | xsb_imports(B, From, CB). |
125 | 119 | xsb_imports(_, file(Path), import(Path)). |
126 | ||
127 | dyn_option_colours(Var, error(instantiation_error)) :- | |
128 | var(Var), | |
129 | !. | |
130 | dyn_option_colours((A,B), functor-[CA, CB]) :- | |
131 | dyn_option_colours(A, CA), | |
132 | dyn_option_colours(B, CB). | |
133 | dyn_option_colours(Opt, identifier) :- | |
134 | valid_dyn_option(Opt), | |
135 | !. | |
136 | dyn_option_colours(_Opt, error(type_error(xsb_dynamic_option))). | |
137 | ||
138 | valid_dyn_option(incremental). | |
139 | valid_dyn_option(abstract(_)). | |
140 | 120 | |
141 | 121 | prolog_colour:style(goal(xsb, _), [colour(blue), underline(true)]). |
142 | 122 |
2 | 2 | Author: Jan Wielemaker and Anjo Anjewierden |
3 | 3 | E-mail: wielemak@science.uva.nl |
4 | 4 | WWW: http://www.swi-prolog.org/packages/xpce/ |
5 | Copyright (c) 2006-2015, University of Amsterdam | |
5 | Copyright (c) 2006-2020, University of Amsterdam | |
6 | SWI-Prolog Solutions b.v. | |
6 | 7 | All rights reserved. |
7 | 8 | |
8 | 9 | Redistribution and use in source and binary forms, with or without |
69 | 70 | format_time/3, |
70 | 71 | maplist/3, |
71 | 72 | strip_module/3, |
72 | xref_called/4 | |
73 | xref_called/4, | |
74 | head_name_arity/3 | |
73 | 75 | ]). |
74 | 76 | |
75 | 77 | gxref_version('0.1.1'). |
1919 | 1921 | predicate_indicator(Goal, Name/Arity) :- |
1920 | 1922 | callable(Goal), |
1921 | 1923 | !, |
1922 | functor(Goal, Name, Arity). | |
1924 | head_name_arity(Goal, Name, Arity). | |
1923 | 1925 | predicate_indicator(Goal, Goal). |
1924 | 1926 | |
1925 | 1927 | hidden_module(user) :- !. |
2104 | 2106 | ). |
2105 | 2107 | |
2106 | 2108 | generated_callable(M:Term) :- |
2107 | functor(Term, Name, Arity), | |
2109 | head_name_arity(Term, Name, Arity), | |
2108 | 2110 | prolog:generated_predicate(M:Name/Arity). |
2109 | 2111 | |
2110 | 2112 | %! xref_called(?Source, ?Callable) is nondet. |
136 | 136 | |
137 | 137 | |
138 | 138 | status |
139 | ws_legal_display_name(char *s) | |
139 | ws_legal_display_name(const char *s) | |
140 | 140 | { succeed; |
141 | 141 | } |
142 | 142 | |
562 | 562 | |
563 | 563 | if ( ca ) |
564 | 564 | { PceString s = &ca->data; |
565 | HGLOBAL mem = ws_string_to_global_mem(s); | |
565 | HGLOBAL mem = ws_string_to_global_mem(s); | |
566 | 566 | |
567 | 567 | if ( mem ) |
568 | 568 | SetClipboardData(CF_UNICODETEXT, mem); |
27 | 27 | COMMON(void) ws_activate_screen_saver(DisplayObj d); |
28 | 28 | COMMON(void) ws_deactivate_screen_saver(DisplayObj d); |
29 | 29 | COMMON(void) ws_init_display(DisplayObj d); |
30 | COMMON(status) ws_legal_display_name(char *s); | |
30 | COMMON(status) ws_legal_display_name(const char *s); | |
31 | 31 | COMMON(status) ws_opened_display(DisplayObj d); |
32 | 32 | COMMON(void) ws_open_display(DisplayObj d); |
33 | 33 | COMMON(void) ws_quit_display(DisplayObj d); |
0 | 0 | /* Part of XPCE --- The SWI-Prolog GUI toolkit |
1 | 1 | |
2 | 2 | Author: Jan Wielemaker and Anjo Anjewierden |
3 | E-mail: jan@swi.psy.uva.nl | |
3 | E-mail: jan@swi-prolog.org | |
4 | 4 | WWW: http://www.swi.psy.uva.nl/projects/xpce/ |
5 | Copyright (c) 1985-2002, University of Amsterdam | |
5 | Copyright (c) 1985-2020, University of Amsterdam | |
6 | SWI-Prolog Solutions b.v. | |
6 | 7 | All rights reserved. |
7 | 8 | |
8 | 9 | Redistribution and use in source and binary forms, with or without |
176 | 177 | } |
177 | 178 | |
178 | 179 | |
180 | const char * | |
181 | skipint(const char *s) | |
182 | { const char *s0 = s; | |
183 | ||
184 | while ( *s && isdigit(*s) ) | |
185 | s++; | |
186 | ||
187 | return s > s0 ? s : NULL; | |
188 | } | |
189 | ||
179 | 190 | status |
180 | ws_legal_display_name(char *s) | |
181 | { char host[LINESIZE]; | |
182 | int display, screen; | |
183 | ||
184 | if ( sscanf(s, "%[a-zA-Z0-9.]:%d.%d", host, &display, &screen) >= 2 ) | |
185 | succeed; | |
186 | ||
187 | fail; | |
191 | ws_legal_display_name(const char *s) | |
192 | { while( *s && (isalnum(*s) || *s == '.') ) | |
193 | s++; | |
194 | if ( *s != ':' ) | |
195 | fail; | |
196 | s++; | |
197 | if ( !(s = skipint(s)) ) | |
198 | fail; | |
199 | if ( *s == '.' ) | |
200 | { s++; | |
201 | if ( !(s = skipint(s)) ) | |
202 | fail; | |
203 | } | |
204 | ||
205 | return *s == '\0'; | |
188 | 206 | } |
189 | 207 | |
190 | 208 | |
228 | 246 | char *theaddress = XDisplayName(address); |
229 | 247 | |
230 | 248 | if ( isDefault(d->address) && !getenv("DISPLAY") ) |
231 | sprintf(problem, "no DISPLAY environment variable"); | |
249 | strcpy(problem, "no DISPLAY environment variable"); | |
232 | 250 | else if ( !ws_legal_display_name(theaddress) ) |
233 | sprintf(problem, "malformed address: %s", theaddress); | |
251 | snprintf(problem, sizeof(problem), "malformed DISPLAY address: %s", | |
252 | theaddress); | |
234 | 253 | else |
235 | 254 | strcpy(problem, "No permission to contact X-server?"); |
236 | 255 |
11 | 11 | ## Publishing |
12 | 12 | |
13 | 13 | snapcraft login (Ubuntu one credentials) |
14 | snapcraft push swi-prolog_<version>.snap | |
14 | snapcraft upload swi-prolog_<version>.snap | |
15 | 15 | snapcraft list-revisions swi-prolog |
16 | snapcraft release swi-prolog 1 beta,edge | |
16 | ||
17 | snapcraft release swi-prolog 1 edge | |
18 | OR | |
19 | snapcraft release swi-prolog 1 stable,candidate,beta | |
17 | 20 | |
18 | 21 | Channels is a list of `stable`, `candidate`, `beta` or `edge` |
19 | 22 |
67 | 67 | /* PLVERSION_TAG: a string, normally "", but for example "rc1" */ |
68 | 68 | |
69 | 69 | #ifndef PLVERSION |
70 | #define PLVERSION 80203 | |
70 | #define PLVERSION 80204 | |
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) 2008-2016, University of Amsterdam | |
5 | Copyright (c) 2008-2020, University of Amsterdam | |
6 | SWI-Prolog Solutions b.v. | |
6 | 7 | All rights reserved. |
7 | 8 | |
8 | 9 | Redistribution and use in source and binary forms, with or without |
43 | 44 | */ |
44 | 45 | |
45 | 46 | test_attvar :- |
46 | run_tests([ attvar, | |
47 | freeze | |
48 | ]). | |
47 | run_tests([ attvar, | |
48 | freeze, | |
49 | attvar_with_occurs_check | |
50 | ]). | |
49 | 51 | |
50 | 52 | :- begin_tests(attvar). |
51 | 53 | |
52 | 54 | test(s_list, L==Codes) :- % Verify wakeup on S_LIST |
53 | string_codes("hello", Codes), | |
54 | freeze(X, X=Codes), | |
55 | append(X, [], L). | |
55 | string_codes("hello", Codes), | |
56 | freeze(X, X=Codes), | |
57 | append(X, [], L). | |
56 | 58 | test(true_ndet, error(existence_error(procedure,_))) :- |
57 | freeze(X, wake(X)), | |
58 | between(-2, 2, X). | |
59 | freeze(X, wake(X)), | |
60 | between(-2, 2, X). | |
59 | 61 | |
60 | 62 | wake(2) :- |
61 | 63 | i_am_undefined. |
65 | 67 | :- begin_tests(freeze). |
66 | 68 | |
67 | 69 | test(freeze_and, true) :- |
68 | freeze(X, true), | |
69 | freeze(Y, true), | |
70 | X=Y, | |
71 | freeze(X, true), | |
72 | X=a. | |
70 | freeze(X, true), | |
71 | freeze(Y, true), | |
72 | X=Y, | |
73 | freeze(X, true), | |
74 | X=a. | |
73 | 75 | |
74 | 76 | :- end_tests(freeze). |
77 | ||
78 | :- begin_tests(attvar_with_occurs_check). | |
79 | ||
80 | test(occurs_check, fail) :- | |
81 | freeze(A, writeln(A)), | |
82 | freeze(B, writeln(B)), | |
83 | Q=[[[A],[B]],x], | |
84 | P=[A|B], | |
85 | unify_with_occurs_check(P, Q). | |
86 | ||
87 | :- end_tests(attvar_with_occurs_check). |
111 | 111 | test(create, true) :- |
112 | 112 | forall(between(1, 100, S), |
113 | 113 | test_create(S)). |
114 | test(convert, error(type_error('dict-key',a(x)))) :- | |
115 | A = [a(x):1, b:2].a, | |
116 | writeln(A). | |
114 | 117 | |
115 | 118 | :- end_tests(dict_create). |
116 | 119 | |
141 | 144 | test('dict_pairs/3') :- |
142 | 145 | dict_pairs(D, a, [k1-v1, k2-v2]), |
143 | 146 | D == a{k1:v1, k2:v2}. |
147 | test('dict_pairs/3', error(type_error('dict-key', "k1"))) :- | |
148 | dict_pairs(_, a, ["k1"-v1, "k2"-v2]). | |
144 | 149 | test('get_dict/3') :- |
145 | 150 | get_dict(k1, a{k1:v1}, V), |
146 | 151 | V == v1. |
535 | 535 | |
536 | 536 | static int |
537 | 537 | utf8_exists_file(const char *name ARG_LD) |
538 | { PL_chars_t txt; | |
538 | { | |
539 | #ifndef __WINDOWS__ | |
540 | PL_chars_t txt; | |
539 | 541 | int rc; |
540 | 542 | |
541 | 543 | PL_STRINGS_MARK(); |
545 | 547 | txt.storage = PL_CHARS_HEAP; |
546 | 548 | txt.canonical = FALSE; |
547 | 549 | rc = ( PL_canonicalise_text(&txt) && |
548 | PL_mb_text(&txt, REP_MB) && | |
550 | PL_mb_text(&txt, REP_FN) && | |
549 | 551 | AccessFile(txt.text.t, ACCESS_EXIST) ); |
550 | 552 | PL_free_text(&txt); |
551 | 553 | PL_STRINGS_RELEASE(); |
552 | 554 | |
553 | 555 | return rc; |
556 | #else | |
557 | return AccessFile(name, ACCESS_EXIST); | |
558 | #endif | |
554 | 559 | } |
555 | 560 | |
556 | 561 | static DIR* |
557 | 562 | utf8_opendir(const char *name ARG_LD) |
558 | { PL_chars_t txt; | |
563 | { | |
564 | #ifndef __WINDOWS__ | |
565 | PL_chars_t txt; | |
559 | 566 | DIR *rc; |
560 | 567 | |
561 | 568 | PL_STRINGS_MARK(); |
565 | 572 | txt.storage = PL_CHARS_HEAP; |
566 | 573 | txt.canonical = FALSE; |
567 | 574 | if ( PL_canonicalise_text(&txt) && |
568 | PL_mb_text(&txt, REP_MB) ) | |
575 | PL_mb_text(&txt, REP_FN) ) | |
569 | 576 | rc = opendir(txt.text.t); |
570 | 577 | else |
571 | 578 | rc = NULL; |
573 | 580 | PL_STRINGS_RELEASE(); |
574 | 581 | |
575 | 582 | return rc; |
583 | #else | |
584 | return opendir(name); | |
585 | #endif | |
576 | 586 | } |
577 | 587 | |
578 | 588 | static int |
837 | 837 | } |
838 | 838 | } |
839 | 839 | /* set the flag value */ |
840 | if ( f->index > 0 ) | |
840 | if ( f->index > 0 && rval ) | |
841 | 841 | { unsigned int mask = (unsigned int)1 << (f->index-1); |
842 | 842 | |
843 | 843 | if ( val ) |
2614 | 2614 | { functor = functorTerm(*arg); |
2615 | 2615 | fdef = valueFunctor(functor); |
2616 | 2616 | |
2617 | if ( !isTextAtom(fdef->name) ) | |
2617 | if ( !isTextAtom(fdef->name) && fdef->name != ATOM_nil ) | |
2618 | 2618 | return NOT_CALLABLE; |
2619 | 2619 | |
2620 | 2620 | if ( true(fdef, ARITH_F) && !ci->islocal ) |
64 | 64 | active non-Prolog slots. |
65 | 65 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
66 | 66 | |
67 | static term_t | |
68 | findReset(LocalFrame fr, term_t ball ARG_LD) | |
67 | #define FRESET_NO_FRAME -1 | |
68 | #define FRESET_FINDALL -2 | |
69 | ||
70 | static int | |
71 | findReset(LocalFrame fr, term_t ball, term_t *rframe ARG_LD) | |
69 | 72 | { Definition reset3 = PROCEDURE_reset3->definition; |
70 | 73 | |
71 | 74 | for(; fr; fr = fr->parent) |
72 | 75 | { int rc; |
73 | 76 | term_t tref; |
77 | static Procedure proc_fl = NULL; | |
78 | ||
79 | if ( !proc_fl ) | |
80 | proc_fl = PL_predicate("findall_loop", 4, "$bags"); | |
81 | ||
82 | if ( fr->predicate == proc_fl->definition ) | |
83 | return FRESET_FINDALL; | |
74 | 84 | |
75 | 85 | if ( fr->predicate != reset3 ) |
76 | 86 | continue; |
80 | 90 | fr = (LocalFrame)valTermRef(tref); |
81 | 91 | |
82 | 92 | if ( rc ) |
83 | { return consTermRef(fr); | |
84 | } | |
85 | } | |
86 | ||
87 | return 0; | |
93 | { *rframe = consTermRef(fr); | |
94 | return TRUE; | |
95 | } | |
96 | } | |
97 | ||
98 | return FRESET_NO_FRAME; | |
88 | 99 | } |
89 | 100 | |
90 | 101 | |
340 | 351 | Code |
341 | 352 | shift(term_t ball ARG_LD) |
342 | 353 | { term_t reset; |
343 | ||
344 | if ( (reset=findReset(environment_frame, ball PASS_LD)) ) | |
354 | int rc; | |
355 | ||
356 | if ( (rc=findReset(environment_frame, ball, &reset PASS_LD)) == TRUE ) | |
345 | 357 | { term_t cont = PL_new_term_ref(); |
346 | 358 | LocalFrame resetfr; |
347 | 359 | LocalFrame fr; |
385 | 397 | return resetfr->programPointer; |
386 | 398 | } |
387 | 399 | |
388 | PL_existence_error("reset/3", ball); | |
389 | return NULL; | |
400 | { static const char *msg[] = | |
401 | { "No matching reset/3 call", | |
402 | "Cannot catch continuation through findall/3" | |
403 | }; | |
404 | ||
405 | return PL_error("shift", 1, msg[-1-rc], | |
406 | ERR_EXISTENCE, ATOM_reset, ball),NULL; | |
407 | } | |
390 | 408 | } |
391 | 409 | |
392 | 410 |
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-2017, VU University Amsterdam | |
5 | Copyright (c) 2013-2020, VU University Amsterdam | |
6 | SWI-Prolog Solutions b.v. | |
6 | 7 | All rights reserved. |
7 | 8 | |
8 | 9 | Redistribution and use in source and binary forms, with or without |
596 | 597 | |
597 | 598 | |
598 | 599 | static int |
599 | get_name_value(Word p, Word name, Word value, Word mark, int flags ARG_LD) | |
600 | get_name_value(Word p, Word name, Word value, mark *m, int flags ARG_LD) | |
600 | 601 | { const char *type; |
601 | 602 | |
602 | 603 | deRef(p); |
617 | 618 | |
618 | 619 | return TRUE; |
619 | 620 | } else |
620 | { gTop = mark; | |
621 | { Undo(*m); | |
621 | 622 | PL_type_error("dict-key", pushWordAsTermRef(np)); |
622 | 623 | popTermRef(); |
623 | 624 | |
639 | 640 | else |
640 | 641 | type = "key-value"; |
641 | 642 | |
642 | gTop = mark; | |
643 | Undo(*m); | |
643 | 644 | PL_type_error(type, pushWordAsTermRef(p)); |
644 | 645 | popTermRef(); |
645 | 646 | |
683 | 684 | |
684 | 685 | if ( PL_is_list(data) ) |
685 | 686 | { intptr_t len = lengthList(data, TRUE); |
686 | Word m, ap, tail; | |
687 | Word ap, dp, tail; | |
688 | mark m; | |
689 | int rc; | |
687 | 690 | |
688 | 691 | if ( len < 0 ) |
689 | 692 | return FALSE; /* not a proper list */ |
690 | retry: | |
691 | if ( !(m = allocGlobal(len*2+2)) ) | |
692 | return FALSE; /* global overflow */ | |
693 | ap = m; | |
693 | ||
694 | if ( unlikely(tTop+1 >= tMax) ) | |
695 | { if ( !makeMoreStackSpace(TRAIL_OVERFLOW, ALLOW_GC|ALLOW_SHIFT) ) | |
696 | return FALSE; | |
697 | } | |
698 | if ( (rc=ensureGlobalSpace(len*2+2, ALLOW_GC)) != TRUE ) | |
699 | return raiseStackOverflow(rc); | |
700 | ap = gTop; | |
701 | Mark(m); | |
702 | dp = ap; | |
694 | 703 | *ap++ = dict_functor(len); |
695 | 704 | if ( tag ) |
696 | 705 | { Word cp = valTermRef(tag); |
697 | 706 | |
698 | 707 | *ap = linkVal(cp); /* TBD: maybe move to another function */ |
699 | 708 | if ( tagex(*ap) == (TAG_REFERENCE|STG_LOCAL) ) |
700 | { if ( unlikely(tTop+1 >= tMax) ) | |
701 | { if ( !makeMoreStackSpace(TRAIL_OVERFLOW, ALLOW_GC|ALLOW_SHIFT) ) | |
702 | return FALSE; | |
703 | gTop = m; | |
704 | goto retry; | |
705 | } | |
706 | deRef(cp) | |
709 | { deRef(cp) | |
707 | 710 | setVar(*ap); |
708 | 711 | Trail(cp, makeRef(ap)); |
709 | 712 | } |
717 | 720 | while( isList(*tail) ) |
718 | 721 | { Word head = HeadList(tail); |
719 | 722 | |
720 | if ( !get_name_value(head, ap+1, ap, m, flags PASS_LD) ) | |
721 | { | |
723 | if ( !get_name_value(head, ap+1, ap, &m, flags PASS_LD) ) | |
722 | 724 | return FALSE; |
723 | } | |
724 | 725 | ap += 2; |
725 | 726 | tail = TailList(tail); |
726 | 727 | deRef(tail); |
727 | 728 | } |
728 | 729 | |
729 | if ( dict_order(m, TRUE PASS_LD) ) | |
730 | if ( dict_order(dp, TRUE PASS_LD) ) | |
730 | 731 | { gTop = ap; |
731 | *valTermRef(dict) = consPtr(m, TAG_COMPOUND|STG_GLOBAL); | |
732 | *valTermRef(dict) = consPtr(dp, TAG_COMPOUND|STG_GLOBAL); | |
732 | 733 | DEBUG(CHK_SECURE, checkStacks(NULL)); |
733 | 734 | return TRUE; |
734 | 735 | } else |
538 | 538 | PL_meta_predicate(PL_predicate("prolog_listen", 3, "system"), "+:+"); |
539 | 539 | PL_meta_predicate(PL_predicate("prolog_unlisten", 2, "system"), "+:"); |
540 | 540 | PL_meta_predicate(PL_predicate("with_tty_raw", 1, "system"), "0"); |
541 | PL_meta_predicate(PL_predicate("$sig_atomic", 1, "system"), "0"); | |
541 | 542 | |
542 | 543 | for( ecell = ext_head; ecell; ecell = ecell->next ) |
543 | 544 | bindExtensions(ecell->module, ecell->extensions); |
4707 | 4707 | |
4708 | 4708 | int |
4709 | 4709 | PL_pending__LD(int sig ARG_LD) |
4710 | { if ( sig > 0 && sig <= MAXSIGNAL && HAS_LD ) | |
4711 | { int off = (sig-1)/32; | |
4712 | int mask = 1 << ((sig-1)%32); | |
4713 | ||
4714 | return (LD->signal.pending[off] & mask) ? TRUE : FALSE; | |
4715 | } | |
4716 | ||
4717 | return -1; | |
4710 | { return pendingSignal(LD, sig); | |
4718 | 4711 | } |
4719 | 4712 | |
4720 | 4713 |
70 | 70 | COMMON(int) foreignWakeup(term_t ex ARG_LD); |
71 | 71 | COMMON(void) updateAlerted(PL_local_data_t *ld); |
72 | 72 | COMMON(int) raiseSignal(PL_local_data_t *ld, int sig); |
73 | COMMON(int) pendingSignal(PL_local_data_t *ld, int sig); | |
73 | 74 | COMMON(Module) contextModule(LocalFrame fr); |
74 | 75 | COMMON(void) setContextModule(LocalFrame fr, Module context); |
75 | 76 | COMMON(int) existingChoice(Choice ch ARG_LD); |
1776 | 1776 | var-VAROFFSET(0), (PC-state->c0)-1)); |
1777 | 1777 | #ifdef O_DEBUG |
1778 | 1778 | if ( DEBUGGING(CHK_SECURE) ) |
1779 | { Word vp = varFrameP(fr, PC[0]); | |
1779 | { Word vp = varFrameP(fr, var); | |
1780 | 1780 | |
1781 | 1781 | if ( !isVar(*vp & ~MARK_MASK) ) |
1782 | 1782 | { Sdprintf("ERROR: [%ld] %s: Wrong clear of var %d, PC=%d\n", |
451 | 451 | { int pending[2]; /* PL_raise() pending signals */ |
452 | 452 | int current; /* currently processing signal */ |
453 | 453 | int is_sync; /* current signal is synchronous */ |
454 | #ifndef __unix__ | |
455 | int forced; /* Forced signal */ | |
456 | #endif | |
454 | 457 | } signal; |
455 | 458 | |
456 | 459 | struct |
678 | 681 | |
679 | 682 | #ifdef O_LIMIT_DEPTH |
680 | 683 | struct |
681 | { uintptr_t limit; | |
682 | uintptr_t reached; | |
684 | { size_t limit; | |
685 | size_t reached; | |
683 | 686 | } depth_info; |
684 | 687 | #endif |
685 | 688 | |
788 | 791 | #define exception_printed (LD->exception.printed) |
789 | 792 | #define gc_status (LD->gc.status) |
790 | 793 | #define debugstatus (LD->_debugstatus) |
791 | #define depth_limit (LD->depth_info.limit) | |
792 | #define depth_reached (LD->depth_info.reached) | |
793 | 794 | #define base_addresses (LD->bases) |
794 | 795 | #define Suser_input (LD->IO.streams[0]) |
795 | 796 | #define Suser_output (LD->IO.streams[1]) |
1645 | 1645 | } registers; |
1646 | 1646 | LocalFrame next_environment; /* See D_BREAK and get_vmi_state() */ |
1647 | 1647 | #ifdef O_LIMIT_DEPTH |
1648 | uintptr_t saved_depth_limit; /* saved values of these */ | |
1649 | uintptr_t saved_depth_reached; | |
1648 | size_t saved_depth_limit; /* saved values of these */ | |
1649 | size_t saved_depth_reached; | |
1650 | 1650 | #endif |
1651 | 1651 | #if O_CATCHTHROW |
1652 | 1652 | term_t exception; /* Exception term */ |
2444 | 2444 | #define SYSTEM_MODE (LD->prolog_flag.access_level == ACCESS_LEVEL_SYSTEM) |
2445 | 2445 | |
2446 | 2446 | #ifdef O_LIMIT_DEPTH |
2447 | #define DEPTH_NO_LIMIT (~(uintptr_t)0x0) /* Highest value */ | |
2447 | #define DEPTH_NO_LIMIT ((size_t)-1) /* Highest value */ | |
2448 | 2448 | #endif |
2449 | 2449 | |
2450 | 2450 | #ifdef O_INFERENCE_LIMIT |
402 | 402 | |
403 | 403 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
404 | 404 | When detected to run under a GNU-Emacs shell or using M-x run-prolog |
405 | from GNU-Emacs, don't pretend we can manipulate the TTY settings. | |
405 | from GNU-Emacs, don't pretend we can manipulate the TTY settings. On | |
406 | Windows, do pretend we have a tty, so the prompt is displayed. | |
406 | 407 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
407 | 408 | |
408 | 409 | static void |
409 | setupGNUEmacsInferiorMode() | |
410 | { char envbuf[4]; | |
410 | setupGNUEmacsInferiorMode(void) | |
411 | { char envbuf[80]; | |
411 | 412 | char *s; |
412 | 413 | int val; |
413 | 414 | |
418 | 419 | |
419 | 420 | clearPrologFlagMask(PLFLAG_TTY_CONTROL); |
420 | 421 | val = TRUE; |
422 | #ifdef __WINDOWS__ | |
423 | Sinput->flags |= SIO_ISATTY; | |
424 | Soutput->flags |= SIO_ISATTY; | |
425 | Serror->flags |= SIO_ISATTY; | |
426 | #endif | |
421 | 427 | } else |
422 | 428 | { val = FALSE; |
423 | 429 | } |
582 | 582 | int |
583 | 583 | setSuperModule(Module m, Module s) |
584 | 584 | { if ( s == m ) |
585 | cannotSetSuperModule(m, s); | |
585 | return cannotSetSuperModule(m, s); | |
586 | 586 | |
587 | 587 | if ( m->supers && !m->supers->next ) |
588 | 588 | { if ( (Module)m->supers->value != s ) |
1283 | 1283 | clearHTable(module->public); |
1284 | 1284 | } |
1285 | 1285 | if ( super ) |
1286 | setSuperModule(module, _lookupModule(super PASS_LD)); | |
1286 | rc = setSuperModule(module, _lookupModule(super PASS_LD)); | |
1287 | 1287 | |
1288 | 1288 | PL_UNLOCK(L_MODULE); |
1289 | 1289 | |
1291 | 1291 | { if ( !PL_unify_nil(rtail) ) |
1292 | 1292 | return FALSE; |
1293 | 1293 | |
1294 | rc = printMessage(ATOM_warning, | |
1295 | PL_FUNCTOR_CHARS, "declare_module", 2, | |
1296 | PL_ATOM, name, | |
1297 | PL_FUNCTOR_CHARS, "abolish", 1, | |
1298 | PL_TERM, rdef); | |
1294 | if ( rc ) | |
1295 | rc = printMessage(ATOM_warning, | |
1296 | PL_FUNCTOR_CHARS, "declare_module", 2, | |
1297 | PL_ATOM, name, | |
1298 | PL_FUNCTOR_CHARS, "abolish", 1, | |
1299 | PL_TERM, rdef); | |
1299 | 1300 | } |
1300 | 1301 | |
1301 | 1302 | return rc; |
221 | 221 | while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) |
222 | 222 | { TranslateMessage(&msg); |
223 | 223 | DispatchMessage(&msg); |
224 | if ( PL_exception(0) ) | |
225 | return FALSE; | |
224 | 226 | } |
225 | 227 | |
226 | 228 | if ( PL_handle_signals() < 0 ) |
650 | 650 | } |
651 | 651 | |
652 | 652 | Mark(m); |
653 | LD->mark_bar = NO_MARK_BAR; /* see also unify_all_trail_ptrs() */ | |
653 | 654 | rc = do_unify(t1, t2 PASS_LD); |
654 | 655 | DiscardMark(m); |
655 | 656 | |
4319 | 4320 | return rc; |
4320 | 4321 | } |
4321 | 4322 | |
4323 | discardBuffer(&b); | |
4324 | ||
4322 | 4325 | split: |
4323 | 4326 | if ( !sep || st.length == 0 ) |
4324 | 4327 | { if ( !sep ) |
4326 | 4329 | |
4327 | 4330 | return PL_domain_error("non_empty_atom", sep); |
4328 | 4331 | } |
4329 | discardBuffer(&b); | |
4332 | ||
4330 | 4333 | return split_atom(list, &st, atom PASS_LD); |
4331 | 4334 | } |
4332 | 4335 | |
4910 | 4913 | /* $depth_limit(+Limit, -OldLimit, -DepthReached) |
4911 | 4914 | */ |
4912 | 4915 | |
4916 | static int | |
4917 | unify_depth_LD(term_t t, size_t depth ARG_LD) | |
4918 | { if ( depth == DEPTH_NO_LIMIT ) | |
4919 | return PL_unify_atom(t, ATOM_inf); | |
4920 | else | |
4921 | return PL_unify_uint64(t, depth); | |
4922 | } | |
4923 | ||
4924 | static int | |
4925 | get_depth_LD(term_t t, size_t *depth ARG_LD) | |
4926 | { atom_t a; | |
4927 | ||
4928 | if ( PL_get_atom(t, &a) && a == ATOM_inf ) | |
4929 | { *depth = DEPTH_NO_LIMIT; | |
4930 | return TRUE; | |
4931 | } | |
4932 | ||
4933 | return PL_get_size_ex(t, depth); | |
4934 | } | |
4935 | ||
4936 | #define unify_depth(t, d) unify_depth_LD(t, d PASS_LD) | |
4937 | #define get_depth(t, d) get_depth_LD(t, d PASS_LD) | |
4938 | ||
4913 | 4939 | static |
4914 | 4940 | PRED_IMPL("$depth_limit", 3, pl_depth_limit, 0) |
4915 | 4941 | { GET_LD |
4916 | long levels; | |
4917 | long clevel = levelFrame(environment_frame) - 1; | |
4918 | ||
4919 | if ( PL_get_long_ex(A1, &levels) ) | |
4920 | { if ( PL_unify_integer(A2, depth_limit) && | |
4921 | PL_unify_integer(A3, depth_reached) ) | |
4922 | { depth_limit = clevel + levels + 1; /* 1 for the catch/3 */ | |
4923 | depth_reached = clevel; | |
4942 | size_t levels; | |
4943 | size_t clevel = levelFrame(environment_frame) - 1; | |
4944 | ||
4945 | if ( PL_get_size_ex(A1, &levels) ) | |
4946 | { if ( unify_depth(A2, LD->depth_info.limit) && | |
4947 | unify_depth(A3, LD->depth_info.reached) ) | |
4948 | { size_t newlimit = clevel + levels + 1; /* 1 for the catch/3 */ | |
4949 | ||
4950 | if ( newlimit < clevel ) | |
4951 | return PL_representation_error("depth_limit"); | |
4952 | ||
4953 | LD->depth_info.limit = newlimit; | |
4954 | LD->depth_info.reached = clevel; | |
4924 | 4955 | |
4925 | 4956 | updateAlerted(LD); |
4926 | succeed; | |
4927 | } | |
4928 | } | |
4929 | ||
4930 | fail; | |
4957 | return TRUE; | |
4958 | } | |
4959 | } | |
4960 | ||
4961 | return FALSE; | |
4931 | 4962 | } |
4932 | 4963 | |
4933 | 4964 | |
4934 | 4965 | static |
4935 | 4966 | PRED_IMPL("$depth_limit_true", 5, pl_depth_limit_true, PL_FA_NONDETERMINISTIC) |
4936 | { term_t limit = A1; | |
4967 | { PRED_LD | |
4968 | term_t limit = A1; | |
4937 | 4969 | term_t olimit = A2; |
4938 | 4970 | term_t oreached = A3; |
4939 | 4971 | term_t res = A4; |
4941 | 4973 | |
4942 | 4974 | switch( CTX_CNTRL ) |
4943 | 4975 | { case FRG_FIRST_CALL: |
4944 | { GET_LD | |
4945 | long l, ol, or; | |
4946 | ||
4947 | if ( PL_get_long_ex(limit, &l) && | |
4948 | PL_get_long_ex(olimit, &ol) && | |
4949 | PL_get_long_ex(oreached, &or) ) | |
4976 | { size_t l, ol, or; | |
4977 | ||
4978 | if ( get_depth(limit, &l) && | |
4979 | get_depth(olimit, &ol) && | |
4980 | get_depth(oreached, &or) ) | |
4950 | 4981 | { intptr_t clevel = levelFrame(environment_frame) - 1; |
4951 | intptr_t used = depth_reached - clevel - 1; | |
4952 | ||
4953 | depth_limit = ol; | |
4954 | depth_reached = or; | |
4982 | intptr_t used = LD->depth_info.reached - clevel - 1; | |
4983 | ||
4984 | LD->depth_info.limit = ol; | |
4985 | LD->depth_info.reached = or; | |
4955 | 4986 | updateAlerted(LD); |
4956 | 4987 | |
4957 | 4988 | if ( used < 1 ) |
4958 | 4989 | used = 1; |
4959 | 4990 | if ( !PL_unify_integer(res, used) ) |
4960 | fail; | |
4991 | return FALSE; | |
4961 | 4992 | |
4962 | 4993 | return unify_det(cut PASS_LD); |
4963 | 4994 | } |
4965 | 4996 | break; |
4966 | 4997 | } |
4967 | 4998 | case FRG_REDO: |
4968 | { GET_LD | |
4969 | long levels; | |
4970 | long clevel = levelFrame(environment_frame) - 1; | |
4971 | ||
4972 | PL_get_long_ex(limit, &levels); | |
4973 | depth_limit = clevel + levels + 1; /* 1 for catch/3 */ | |
4974 | depth_reached = clevel; | |
4999 | { size_t levels; | |
5000 | size_t clevel = levelFrame(environment_frame) - 1; | |
5001 | ||
5002 | if ( !get_depth(limit, &levels) ) | |
5003 | return FALSE; | |
5004 | LD->depth_info.limit = clevel + levels + 1; /* 1 for catch/3 */ | |
5005 | LD->depth_info.reached = clevel; | |
4975 | 5006 | updateAlerted(LD); |
4976 | 5007 | |
4977 | fail; /* backtrack to goal */ | |
5008 | return FALSE; /* backtrack to goal */ | |
4978 | 5009 | } |
4979 | 5010 | case FRG_CUTTED: |
4980 | succeed; | |
4981 | } | |
4982 | ||
4983 | fail; | |
5011 | return TRUE; | |
5012 | } | |
5013 | ||
5014 | return FALSE; | |
4984 | 5015 | } |
4985 | 5016 | |
4986 | 5017 | |
4987 | 5018 | static |
4988 | 5019 | PRED_IMPL("$depth_limit_false", 3, depth_limit_false, 0) |
4989 | 5020 | { PRED_LD |
4990 | long ol, or; | |
4991 | ||
4992 | if ( PL_get_long_ex(A1, &ol) && | |
4993 | PL_get_long_ex(A2, &or) ) | |
4994 | { int exceeded = (depth_reached > depth_limit); | |
4995 | ||
4996 | depth_limit = ol; | |
4997 | depth_reached = or; | |
5021 | size_t ol, or; | |
5022 | ||
5023 | if ( get_depth(A1, &ol) && | |
5024 | get_depth(A2, &or) ) | |
5025 | { int exceeded = (LD->depth_info.reached > LD->depth_info.limit); | |
5026 | ||
5027 | LD->depth_info.limit = ol; | |
5028 | LD->depth_info.reached = or; | |
4998 | 5029 | updateAlerted(LD); |
4999 | 5030 | |
5000 | 5031 | if ( exceeded ) |
5001 | 5032 | return PL_unify_atom(A3, ATOM_depth_limit_exceeded); |
5002 | 5033 | } |
5003 | 5034 | |
5004 | fail; | |
5035 | return FALSE; | |
5005 | 5036 | } |
5006 | 5037 | |
5007 | 5038 | |
5008 | 5039 | static |
5009 | 5040 | PRED_IMPL("$depth_limit_except", 3, depth_limit_except, 0) |
5010 | 5041 | { PRED_LD |
5011 | long ol, or; | |
5012 | ||
5013 | if ( PL_get_long_ex(A1, &ol) && | |
5014 | PL_get_long_ex(A2, &or) ) | |
5015 | { depth_limit = ol; | |
5016 | depth_reached = or; | |
5042 | size_t ol, or; | |
5043 | ||
5044 | if ( get_depth(A1, &ol) && | |
5045 | get_depth(A2, &or) ) | |
5046 | { LD->depth_info.limit = ol; | |
5047 | LD->depth_info.reached = or; | |
5017 | 5048 | updateAlerted(LD); |
5018 | 5049 | |
5019 | 5050 | return PL_raise_exception(A3); |
74 | 74 | } |
75 | 75 | |
76 | 76 | #ifdef O_LIMIT_DEPTH |
77 | depth_limit = (uintptr_t)DEPTH_NO_LIMIT; | |
77 | LD->depth_info.limit = DEPTH_NO_LIMIT; | |
78 | 78 | #endif |
79 | 79 | |
80 | 80 | LD->autoload.nesting = NULL; |
125 | 125 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
126 | 126 | lingerDefinition() deals with (undefined) definitions that are replaced |
127 | 127 | due to importing. These definitions can be in use with other threads. |
128 | This needs be be improved, possibly using a technique similar to the RDF | |
128 | This needs to be improved, possibly using a technique similar to the RDF | |
129 | 129 | database. For now, we merely collect them in a single place, so we know |
130 | 130 | what is going on. In addition, we can collect lingering definitions when |
131 | 131 | destroying a module, resulting in leak-free temporary modules. |
1428 | 1428 | retractClauseDefinition(Definition def, Clause clause) |
1429 | 1429 | { GET_LD |
1430 | 1430 | size_t size = sizeofClause(clause->code_size) + SIZEOF_CREF_CLAUSE; |
1431 | gen_t egen; | |
1431 | 1432 | |
1432 | 1433 | if ( def->events && |
1433 | 1434 | !predicate_update_event(def, ATOM_retract, clause PASS_LD) ) |
1447 | 1448 | if ( false(clause, UNIT_CLAUSE) ) |
1448 | 1449 | def->impl.clauses.number_of_rules--; |
1449 | 1450 | #ifdef O_LOGICAL_UPDATE |
1450 | clause->generation.erased = next_global_generation(); | |
1451 | do | |
1452 | { egen = global_generation()+1; | |
1453 | clause->generation.erased = egen; | |
1454 | } while (egen < next_global_generation()); | |
1451 | 1455 | setLastModifiedPredicate(def, clause->generation.erased); |
1452 | 1456 | #endif |
1453 | 1457 | DEBUG(CHK_SECURE, checkDefinition(def)); |
2376 | 2380 | { DEBUG(MSG_PROC_COUNT, Sdprintf("Delayed unalloc %s\n", predicateName(def))); |
2377 | 2381 | assert(def->module == NULL); |
2378 | 2382 | if ( def->impl.clauses.first_clause == NULL ) |
2379 | { if ( def->lingering ) | |
2380 | { static int done = FALSE; | |
2381 | if ( !done ) | |
2382 | { Sdprintf("maybeUnregisterDirtyDefinition(%s): lingering data\n", | |
2383 | predicateName(def)); | |
2384 | done = TRUE; | |
2385 | } | |
2386 | } | |
2383 | { DEBUG(0, | |
2384 | if ( def->lingering ) | |
2385 | { Sdprintf("maybeUnregisterDirtyDefinition(%s): lingering data\n", | |
2386 | predicateName(def)); | |
2387 | }); | |
2387 | 2388 | unregisterDirtyDefinition(def); |
2388 | 2389 | deleteIndexes(&def->impl.clauses, TRUE); |
2389 | 2390 | freeHeap(def->impl.any.args, sizeof(arg_info)*def->functor->arity); |
2942 | 2943 | ForeignRedoPtr(ctx); |
2943 | 2944 | } else |
2944 | 2945 | { setGenerationFrame(environment_frame); |
2945 | assert(dref); | |
2946 | dref->generation = generationFrame(environment_frame); | |
2947 | 2946 | DEBUG(MSG_CGC_RETRACT, |
2948 | 2947 | Sdprintf("Retract: first clause deleted; set gen to %lld\n", |
2949 | 2948 | generationFrame(environment_frame))); |
159 | 159 | initPrologLocalData(ARG1_LD) |
160 | 160 | { |
161 | 161 | #ifdef O_LIMIT_DEPTH |
162 | depth_limit = DEPTH_NO_LIMIT; | |
162 | LD->depth_info.limit = DEPTH_NO_LIMIT; | |
163 | 163 | #endif |
164 | 164 | #ifdef O_INFERENCE_LIMIT |
165 | 165 | LD->inference_limit.limit = INFERENCE_NO_LIMIT; |
506 | 506 | { term_t sigterm = PL_new_term_ref(); |
507 | 507 | qid_t qid; |
508 | 508 | #ifdef O_LIMIT_DEPTH |
509 | uintptr_t olimit = depth_limit; | |
510 | depth_limit = DEPTH_NO_LIMIT; | |
509 | size_t olimit = LD->depth_info.limit; | |
510 | LD->depth_info.limit = DEPTH_NO_LIMIT; | |
511 | 511 | #endif |
512 | 512 | |
513 | 513 | PL_put_atom_chars(sigterm, signal_name(sig)); |
518 | 518 | if ( PL_next_solution(qid) ) {}; /* cannot ignore return */ |
519 | 519 | PL_cut_query(qid); |
520 | 520 | #ifdef O_LIMIT_DEPTH |
521 | depth_limit = olimit; | |
521 | LD->depth_info.limit = olimit; | |
522 | 522 | #endif |
523 | 523 | } else if ( true(sh, PLSIG_THROW) ) |
524 | 524 | { char *predname; |
536 | 536 | } else if ( sh->handler ) |
537 | 537 | { int ex_pending = (exception_term && !sync); |
538 | 538 | #ifdef O_LIMIT_DEPTH |
539 | uintptr_t olimit = depth_limit; | |
540 | depth_limit = DEPTH_NO_LIMIT; | |
539 | uintptr_t olimit = LD->depth_info.limit; | |
540 | LD->depth_info.limit = DEPTH_NO_LIMIT; | |
541 | 541 | #endif |
542 | 542 | (*sh->handler)(sig); |
543 | 543 | #ifdef O_LIMIT_DEPTH |
544 | depth_limit = olimit; | |
544 | LD->depth_info.limit = olimit; | |
545 | 545 | #endif |
546 | 546 | |
547 | 547 | DEBUG(MSG_SIGNAL, |
1060 | 1060 | PL_handle_signals(void) |
1061 | 1061 | { GET_LD |
1062 | 1062 | |
1063 | if ( !HAS_LD || LD->critical || !is_signalled(PASS_LD1) ) | |
1063 | if ( !is_signalled(PASS_LD1) ) | |
1064 | 1064 | return 0; |
1065 | if ( exception_term ) | |
1066 | return -1; | |
1067 | ||
1068 | return handleSignals(PASS_LD1); | |
1069 | } | |
1070 | ||
1065 | else | |
1066 | return handleSignals(PASS_LD1); | |
1067 | } | |
1068 | ||
1069 | #ifndef __unix__ | |
1070 | static int | |
1071 | handleSigInt(ARG1_LD) | |
1072 | { int intmask = 1<<(SIGINT-1); | |
1073 | ||
1074 | if ( LD->signal.forced == SIGINT && LD->signal.pending[0] & intmask ) | |
1075 | { ATOMIC_AND(&LD->signal.pending[0], ~intmask); | |
1076 | ||
1077 | LD->signal.forced = 0; | |
1078 | dispatch_signal(SIGINT, TRUE); | |
1079 | ||
1080 | if ( exception_term ) | |
1081 | return -1; | |
1082 | updateAlerted(LD); | |
1083 | ||
1084 | return 1; | |
1085 | } | |
1086 | ||
1087 | return 0; | |
1088 | } | |
1089 | #endif | |
1071 | 1090 | |
1072 | 1091 | int |
1073 | 1092 | handleSignals(ARG1_LD) |
1074 | 1093 | { int done = 0; |
1075 | 1094 | int i; |
1076 | 1095 | |
1077 | if ( !HAS_LD || LD->critical ) | |
1096 | if ( !is_signalled(PASS_LD1) ) | |
1097 | return 0; | |
1098 | if ( !HAS_LD ) | |
1099 | return 0; | |
1100 | if ( exception_term ) | |
1101 | return -1; | |
1102 | #ifndef __unix__ /* on Unix we ask to signal twice */ | |
1103 | if ( (done=handleSigInt(PASS_LD1)) ) | |
1104 | return done; | |
1105 | #endif | |
1106 | if ( LD->critical ) | |
1078 | 1107 | return 0; |
1079 | 1108 | |
1080 | 1109 | for(i=0; i<2; i++) |
1463 | 1463 | { PL_thread_info_t *info = GD->thread.threads[i]; |
1464 | 1464 | |
1465 | 1465 | if ( info && info->w32id == id && info->thread_data ) |
1466 | { raiseSignal(info->thread_data, sig); | |
1467 | if ( info->w32id ) | |
1468 | PostThreadMessage(info->w32id, WM_SIGNALLED, 0, 0L); | |
1466 | { PL_local_data_t *ld = info->thread_data; | |
1467 | ||
1469 | 1468 | PL_UNLOCK(L_THREAD); |
1469 | if ( pendingSignal(ld, sig) ) | |
1470 | ld->signal.forced = sig; | |
1471 | else | |
1472 | raiseSignal(ld, sig); | |
1473 | PostThreadMessage(id, WM_SIGNALLED, 0, 0L); | |
1470 | 1474 | DEBUG(MSG_THREAD, Sdprintf("Signalled %d to thread %d\n", sig, i)); |
1471 | 1475 | return TRUE; |
1472 | 1476 | } |
3034 | 3038 | if ( rval ) |
3035 | 3039 | { |
3036 | 3040 | #ifdef O_LIMIT_DEPTH |
3037 | uintptr_t olimit = depth_limit; | |
3038 | depth_limit = DEPTH_NO_LIMIT; | |
3041 | size_t olimit = LD->depth_info.limit; | |
3042 | LD->depth_info.limit = DEPTH_NO_LIMIT; | |
3039 | 3043 | #endif |
3040 | 3044 | rval = callProlog(gm, goal, PL_Q_CATCH_EXCEPTION, &ex); |
3041 | 3045 | #ifdef O_LIMIT_DEPTH |
3042 | depth_limit = olimit; | |
3046 | LD->depth_info.limit = olimit; | |
3043 | 3047 | #endif |
3044 | 3048 | } else |
3045 | 3049 | { rval = raiseStackOverflow(GLOBAL_OVERFLOW); |
214 | 214 | { GET_LD |
215 | 215 | |
216 | 216 | #ifdef O_PLMT |
217 | if ( PL_thread_self() > 1 ) | |
217 | if ( PL_thread_self() > 1 && !LD->exit_requested ) | |
218 | 218 | { Sfprintf(Sdout, "%sexit session\n", msg); |
219 | 219 | LD->exit_requested = EXIT_REQ_THREAD; |
220 | 220 | return ACTION_ABORT; |
950 | 950 | if ( debugstatus.showContext ) |
951 | 951 | Sfprintf(out, "[%s] ", stringAtom(contextModule(frame)->name)); |
952 | 952 | #ifdef O_LIMIT_DEPTH |
953 | if ( levelFrame(frame) > depth_limit ) | |
953 | if ( levelFrame(frame) > LD->depth_info.limit ) | |
954 | 954 | Sfprintf(out, "[depth-limit exceeded] "); |
955 | 955 | #endif |
956 | 956 | |
1635 | 1635 | return; |
1636 | 1636 | } |
1637 | 1637 | } else |
1638 | { safe = TRUE; | |
1639 | } | |
1640 | #else | |
1641 | safe = !LD->critical; | |
1638 | 1642 | #endif /* no async signals; always safe */ |
1639 | { safe = TRUE; | |
1640 | } | |
1641 | 1643 | |
1642 | 1644 | Sreset(); |
1643 | 1645 | again: |
975 | 975 | |
976 | 976 | stats->nodes++; |
977 | 977 | stats->bytes += sizeof(*n); |
978 | if ( n->value ) | |
978 | if ( n->value && true(n, TN_PRIMARY) ) | |
979 | 979 | stats->values++; |
980 | 980 | |
981 | 981 | if ( children.any ) |
1282 | 1282 | void |
1283 | 1283 | trie_delete(trie *trie, trie_node *node, int prune) |
1284 | 1284 | { if ( node->value ) |
1285 | { clear(node, (TN_PRIMARY|TN_SECONDARY)); | |
1285 | { if ( true(node, TN_PRIMARY) ) | |
1286 | ATOMIC_DEC(&trie->value_count); | |
1287 | ||
1288 | clear(node, (TN_PRIMARY|TN_SECONDARY)); | |
1286 | 1289 | if ( prune && trie->references == 0 ) |
1287 | 1290 | { prune_node(trie, node); |
1288 | 1291 | } else |
1296 | 1299 | release_value(v); |
1297 | 1300 | } |
1298 | 1301 | } |
1299 | ATOMIC_DEC(&trie->value_count); | |
1300 | 1302 | trie_discard_clause(trie); |
1301 | 1303 | } |
1302 | 1304 | } |
2354 | 2356 | stat_trie(trie, &stats); |
2355 | 2357 | if ( stats.nodes != trie->node_count ) |
2356 | 2358 | Sdprintf("OOPS: trie_property/2: counted %zd nodes, admin says %zd\n", |
2357 | stats.nodes, trie->node_count); | |
2359 | (size_t)stats.nodes, (size_t)trie->node_count); | |
2358 | 2360 | if ( stats.values != trie->value_count ) |
2359 | 2361 | Sdprintf("OOPS: trie_property/2: counted %zd values, admin says %zd\n", |
2360 | stats.values, trie->value_count); | |
2362 | (size_t)stats.values, (size_t)trie->value_count); | |
2361 | 2363 | // assert(stats.nodes == trie->node_count); |
2362 | 2364 | // assert(stats.values == trie->value_count); |
2363 | 2365 | return PL_unify_int64(arg, stats.bytes); |
1588 | 1588 | if ( unlikely(LD->alerted) ) |
1589 | 1589 | { /* play safe */ |
1590 | 1590 | lTop = (LocalFrame) argFrameP(FR, DEF->functor->arity); |
1591 | PC = DEF->codes; | |
1591 | 1592 | |
1592 | 1593 | /* we need the autoloader and get back */ |
1593 | 1594 | if ( DEF->codes[0] == encode(S_VIRGIN) && |
1623 | 1624 | Profile(FR->prof_node = profCall(DEF PASS_LD)); |
1624 | 1625 | |
1625 | 1626 | #ifdef O_LIMIT_DEPTH |
1626 | { unsigned int depth = levelFrame(FR); | |
1627 | ||
1628 | if ( depth > depth_reached ) | |
1629 | depth_reached = depth; | |
1630 | if ( depth > depth_limit ) | |
1627 | { size_t depth = levelFrame(FR); | |
1628 | ||
1629 | if ( depth > LD->depth_info.reached ) | |
1630 | LD->depth_info.reached = depth; | |
1631 | if ( depth > LD->depth_info.limit ) | |
1631 | 1632 | { DEBUG(2, Sdprintf("depth-limit\n")); |
1632 | 1633 | |
1633 | 1634 | if ( debugstatus.debugging ) |
312 | 312 | } |
313 | 313 | |
314 | 314 | return FALSE; |
315 | } | |
316 | ||
317 | ||
318 | int | |
319 | pendingSignal(PL_local_data_t *ld, int sig) | |
320 | { if ( sig > 0 && sig <= MAXSIGNAL && ld ) | |
321 | { int off = (sig-1)/32; | |
322 | int mask = 1 << ((sig-1)%32); | |
323 | ||
324 | return (ld->signal.pending[off] & mask) ? TRUE : FALSE; | |
325 | } | |
326 | ||
327 | return -1; | |
315 | 328 | } |
316 | 329 | |
317 | 330 | |
2538 | 2551 | qf->flags_saved = (LD->prolog_flag.mask.flags & NDEBUG_SAVE_FLAGS); |
2539 | 2552 | setPrologFlagMask(PLFLAG_LASTCALL); |
2540 | 2553 | #ifdef O_LIMIT_DEPTH |
2541 | qf->saved_depth_limit = depth_limit; | |
2542 | qf->saved_depth_reached = depth_reached; | |
2543 | depth_limit = DEPTH_NO_LIMIT; | |
2554 | qf->saved_depth_limit = LD->depth_info.limit; | |
2555 | qf->saved_depth_reached = LD->depth_info.reached; | |
2556 | LD->depth_info.limit = DEPTH_NO_LIMIT; | |
2544 | 2557 | #endif |
2545 | 2558 | } |
2546 | 2559 | fr->predicate = def; |
2617 | 2630 | LD->prolog_flag.mask.flags &= (~NDEBUG_SAVE_FLAGS); |
2618 | 2631 | LD->prolog_flag.mask.flags |= qf->flags_saved; |
2619 | 2632 | #ifdef O_LIMIT_DEPTH |
2620 | depth_limit = qf->saved_depth_limit; | |
2621 | depth_reached = qf->saved_depth_reached; | |
2633 | LD->depth_info.limit = qf->saved_depth_limit; | |
2634 | LD->depth_info.reached = qf->saved_depth_reached; | |
2622 | 2635 | #endif /*O_LIMIT_DEPTH*/ |
2623 | 2636 | } |
2624 | 2637 | updateAlerted(LD); |
2680 | 2680 | run_scripts(T). |
2681 | 2681 | |
2682 | 2682 | script_failed(File, fail) :- |
2683 | !, | |
2683 | 2684 | format(user_error, '~NScript ~w failed~n', [File]), |
2684 | 2685 | assert(failed(script(File))). |
2685 | 2686 | script_failed(File, Except) :- |
1122 | 1122 | if ( rlc_kill(b) ) |
1123 | 1123 | return 0; |
1124 | 1124 | break; |
1125 | } | |
1126 | ||
1127 | if ( (name = lookupMenuId(item)) ) | |
1128 | { if ( _rlc_menu_hook ) | |
1129 | { (*_rlc_menu_hook)(b, name); | |
1130 | } | |
1131 | ||
1132 | return 0; | |
1125 | default: | |
1126 | if ( (name = lookupMenuId(item)) ) | |
1127 | { if ( _rlc_menu_hook ) | |
1128 | { (*_rlc_menu_hook)(b, name); | |
1129 | } | |
1130 | ||
1131 | return 0; | |
1132 | } | |
1133 | 1133 | } |
1134 | 1134 | |
1135 | 1135 | break; |
1427 | 1427 | static int |
1428 | 1428 | rlc_get_message(MSG *msg, HWND hwnd, UINT low, UINT high) |
1429 | 1429 | { int rc; |
1430 | ||
1430 | 1431 | again: |
1431 | if ( (rc=GetMessage(msg, hwnd, low, high)) ) | |
1432 | if ( (rc=PeekMessage(msg, hwnd, low, WM_RLC_INPUT, PM_REMOVE)) ) | |
1433 | { if ( _rlc_message_hook && | |
1434 | (*_rlc_message_hook)(msg->hwnd, msg->message, | |
1435 | msg->wParam, msg->lParam) ) | |
1436 | goto again; | |
1437 | } else if ( (rc=GetMessage(msg, hwnd, low, high)) ) | |
1432 | 1438 | { if ( _rlc_message_hook && |
1433 | 1439 | (*_rlc_message_hook)(msg->hwnd, msg->message, |
1434 | 1440 | msg->wParam, msg->lParam) ) |
2321 | 2327 | b->imodeswitch = FALSE; |
2322 | 2328 | b->lhead = NULL; |
2323 | 2329 | b->ltail = NULL; |
2330 | InitializeCriticalSection(&b->lock); | |
2324 | 2331 | |
2325 | 2332 | memset(b->lines, 0, sizeof(text_line) * h); |
2326 | 2333 | for(i=0; i<h; i++) |
3425 | 3432 | if ( !b ) |
3426 | 3433 | return -1; |
3427 | 3434 | |
3435 | EnterCriticalSection(&b->lock); | |
3428 | 3436 | for(s=buf, e=&buf[count]; s<e; s++) |
3429 | 3437 | { if ( *s == '\n' ) |
3430 | 3438 | b->promptlen = 0; |
3431 | 3439 | else if ( b->promptlen < MAXPROMPT-1 ) |
3432 | 3440 | b->promptbuf[b->promptlen++] = *s; |
3433 | 3441 | } |
3442 | LeaveCriticalSection(&b->lock); | |
3434 | 3443 | |
3435 | 3444 | if ( b->window ) |
3436 | 3445 | { if ( SendMessageTimeout(b->window, |
3467 | 3476 | } |
3468 | 3477 | if ( b->read_buffer.line ) |
3469 | 3478 | free(b->read_buffer.line); |
3479 | DeleteCriticalSection(&b->lock); | |
3470 | 3480 | |
3471 | 3481 | free(b); |
3472 | 3482 | } |
171 | 171 | DWORD console_thread_id; /* I/O thread id */ |
172 | 172 | DWORD application_thread_id; |
173 | 173 | HWND kill_window; /* window in app thread for destroy */ |
174 | CRITICAL_SECTION lock; /* Serialized actions */ | |
174 | 175 | |
175 | 176 | user_data values[MAX_USER_VALUES]; /* associated user data */ |
176 | 177 | } rlc_data, *RlcData; |