View source with raw comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  1997-2021, University of Amsterdam
    7                              VU University Amsterdam
    8                              CWI, Amsterdam
    9                              SWI-Prolog Solutions b.v.
   10    All rights reserved.
   11
   12    Redistribution and use in source and binary forms, with or without
   13    modification, are permitted provided that the following conditions
   14    are met:
   15
   16    1. Redistributions of source code must retain the above copyright
   17       notice, this list of conditions and the following disclaimer.
   18
   19    2. Redistributions in binary form must reproduce the above copyright
   20       notice, this list of conditions and the following disclaimer in
   21       the documentation and/or other materials provided with the
   22       distribution.
   23
   24    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   25    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   26    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   27    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   28    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   29    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   30    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   31    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   32    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   34    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   35    POSSIBILITY OF SUCH DAMAGE.
   36*/
   37
   38:- module('$messages',
   39          [ print_message/2,            % +Kind, +Term
   40            print_message_lines/3,      % +Stream, +Prefix, +Lines
   41            message_to_string/2         % +Term, -String
   42          ]).   43
   44:- multifile
   45    prolog:message//1,              % entire message
   46    prolog:error_message//1,        % 1-st argument of error term
   47    prolog:message_context//1,      % Context of error messages
   48    prolog:deprecated//1,	    % Deprecated features
   49    prolog:message_location//1,     % (File) location of error messages
   50    prolog:message_line_element/2.  % Extend printing
   51:- '$hide'((
   52    prolog:message//1,
   53    prolog:error_message//1,
   54    prolog:message_context//1,
   55    prolog:deprecated//1,
   56    prolog:message_location//1,
   57    prolog:message_line_element/2)).   58% Lang, Term versions
   59:- multifile
   60    prolog:message//2,              % entire message
   61    prolog:error_message//2,        % 1-st argument of error term
   62    prolog:message_context//2,      % Context of error messages
   63    prolog:message_location//2,	    % (File) location of error messages
   64    prolog:deprecated//2.	    % Deprecated features
   65:- '$hide'((
   66    prolog:message//2,
   67    prolog:error_message//2,
   68    prolog:message_context//2,
   69    prolog:deprecated//2,
   70    prolog:message_location//2)).   71
   72:- discontiguous
   73    prolog_message/3.   74
   75:- public
   76    translate_message//1,           % +Message (deprecated)
   77    prolog:translate_message//1.    % +Message
   78
   79:- create_prolog_flag(message_context, [thread], []).
 translate_message(+Term)// is det
Translate a message Term into message lines. The produced lines is a list of
nl
Emit a newline
Fmt - Args
Emit the result of format(Fmt, Args)
Fmt
Emit the result of format(Fmt)
ansi(Code, Fmt, Args)
Use ansi_format/3 for color output.
flush
Used only as last element of the list. Simply flush the output instead of producing a final newline.
at_same_line
Start the messages at the same line (instead of using ~N)
deprecated
- Use code for message translation should call translate_message//1.
  103prolog:translate_message(Term) -->
  104    translate_message(Term).
 translate_message(+Term)// is det
Translate a message term into message lines. This version may be called from user and library definitions for message translation.
  111translate_message(Term) -->
  112    { nonvar(Term) },
  113    (   { message_lang(Lang) },
  114        prolog:message(Lang, Term)
  115    ;   prolog:message(Term)
  116    ),
  117    !.
  118translate_message(Term) -->
  119    { nonvar(Term) },
  120    translate_message2(Term),
  121    !.
  122translate_message(Term) -->
  123    { nonvar(Term),
  124      Term = error(_, _)
  125    },
  126    [ 'Unknown exception: ~p'-[Term] ].
  127translate_message(Term) -->
  128    [ 'Unknown message: ~p'-[Term] ].
  129
  130translate_message2(Term) -->
  131    prolog_message(Term).
  132translate_message2(error(resource_error(stack), Context)) -->
  133    !,
  134    out_of_stack(Context).
  135translate_message2(error(resource_error(tripwire(Wire, Context)), _)) -->
  136    !,
  137    tripwire_message(Wire, Context).
  138translate_message2(error(existence_error(reset, Ball), SWI)) -->
  139    swi_location(SWI),
  140    tabling_existence_error(Ball, SWI).
  141translate_message2(error(ISO, SWI)) -->
  142    swi_location(SWI),
  143    term_message(ISO),
  144    swi_extra(SWI).
  145translate_message2('$aborted') -->
  146    [ 'Execution Aborted' ].
  147translate_message2(message_lines(Lines), L, T) :- % deal with old C-warning()
  148    make_message_lines(Lines, L, T).
  149translate_message2(format(Fmt, Args)) -->
  150    [ Fmt-Args ].
  151
  152make_message_lines([], T, T) :- !.
  153make_message_lines([Last],  ['~w'-[Last]|T], T) :- !.
  154make_message_lines([L0|LT], ['~w'-[L0],nl|T0], T) :-
  155    make_message_lines(LT, T0, T).
 term_message(+Term)//
Deal with the formal argument of error(Format, ImplDefined) exception terms. The ImplDefined argument is handled by swi_location//2.
  163:- public term_message//1.  164term_message(Term) -->
  165    {var(Term)},
  166    !,
  167    [ 'Unknown error term: ~p'-[Term] ].
  168term_message(Term) -->
  169    { message_lang(Lang) },
  170    prolog:error_message(Lang, Term),
  171    !.
  172term_message(Term) -->
  173    prolog:error_message(Term),
  174    !.
  175term_message(Term) -->
  176    iso_message(Term).
  177term_message(Term) -->
  178    swi_message(Term).
  179term_message(Term) -->
  180    [ 'Unknown error term: ~p'-[Term] ].
  181
  182iso_message(resource_error(Missing)) -->
  183    [ 'Not enough resources: ~w'-[Missing] ].
  184iso_message(type_error(evaluable, Actual)) -->
  185    { callable(Actual) },
  186    [ 'Arithmetic: `~p'' is not a function'-[Actual] ].
  187iso_message(type_error(free_of_attvar, Actual)) -->
  188    [ 'Type error: `~W'' contains attributed variables'-
  189      [Actual,[portray(true), attributes(portray)]] ].
  190iso_message(type_error(Expected, Actual)) -->
  191    [ 'Type error: `~w'' expected, found `~p'''-[Expected, Actual] ],
  192    type_error_comment(Expected, Actual).
  193iso_message(domain_error(Domain, Actual)) -->
  194    [ 'Domain error: '-[] ], domain(Domain),
  195    [ ' expected, found `~p'''-[Actual] ].
  196iso_message(instantiation_error) -->
  197    [ 'Arguments are not sufficiently instantiated' ].
  198iso_message(uninstantiation_error(Var)) -->
  199    [ 'Uninstantiated argument expected, found ~p'-[Var] ].
  200iso_message(representation_error(What)) -->
  201    [ 'Cannot represent due to `~w'''-[What] ].
  202iso_message(permission_error(Action, Type, Object)) -->
  203    permission_error(Action, Type, Object).
  204iso_message(evaluation_error(Which)) -->
  205    [ 'Arithmetic: evaluation error: `~p'''-[Which] ].
  206iso_message(existence_error(procedure, Proc)) -->
  207    [ 'Unknown procedure: ~q'-[Proc] ],
  208    unknown_proc_msg(Proc).
  209iso_message(existence_error(answer_variable, Var)) -->
  210    [ '$~w was not bound by a previous query'-[Var] ].
  211iso_message(existence_error(matching_rule, Goal)) -->
  212    [ 'No rule matches ~p'-[Goal] ].
  213iso_message(existence_error(Type, Object)) -->
  214    [ '~w `~p'' does not exist'-[Type, Object] ].
  215iso_message(existence_error(Type, Object, In)) --> % not ISO
  216    [ '~w `~p'' does not exist in ~p'-[Type, Object, In] ].
  217iso_message(busy(Type, Object)) -->
  218    [ '~w `~p'' is busy'-[Type, Object] ].
  219iso_message(syntax_error(swi_backslash_newline)) -->
  220    [ 'Deprecated ... \\<newline><white>*.  Use \\c' ].
  221iso_message(syntax_error(Id)) -->
  222    [ 'Syntax error: ' ],
  223    syntax_error(Id).
  224iso_message(occurs_check(Var, In)) -->
  225    [ 'Cannot unify ~p with ~p: would create an infinite tree'-[Var, In] ].
 permission_error(Action, Type, Object)//
Translate permission errors. Most follow te pattern "No permission to Action Type Object", but some are a bit different.
  232permission_error(Action, built_in_procedure, Pred) -->
  233    { user_predicate_indicator(Pred, PI)
  234    },
  235    [ 'No permission to ~w built-in predicate `~p'''-[Action, PI] ],
  236    (   {Action \== export}
  237    ->  [ nl,
  238          'Use :- redefine_system_predicate(+Head) if redefinition is intended'
  239        ]
  240    ;   []
  241    ).
  242permission_error(import_into(Dest), procedure, Pred) -->
  243    [ 'No permission to import ~p into ~w'-[Pred, Dest] ].
  244permission_error(Action, static_procedure, Proc) -->
  245    [ 'No permission to ~w static procedure `~p'''-[Action, Proc] ],
  246    defined_definition('Defined', Proc).
  247permission_error(input, stream, Stream) -->
  248    [ 'No permission to read from output stream `~p'''-[Stream] ].
  249permission_error(output, stream, Stream) -->
  250    [ 'No permission to write to input stream `~p'''-[Stream] ].
  251permission_error(input, text_stream, Stream) -->
  252    [ 'No permission to read bytes from TEXT stream `~p'''-[Stream] ].
  253permission_error(output, text_stream, Stream) -->
  254    [ 'No permission to write bytes to TEXT stream `~p'''-[Stream] ].
  255permission_error(input, binary_stream, Stream) -->
  256    [ 'No permission to read characters from binary stream `~p'''-[Stream] ].
  257permission_error(output, binary_stream, Stream) -->
  258    [ 'No permission to write characters to binary stream `~p'''-[Stream] ].
  259permission_error(open, source_sink, alias(Alias)) -->
  260    [ 'No permission to reuse alias "~p": already taken'-[Alias] ].
  261permission_error(tnot, non_tabled_procedure, Pred) -->
  262    [ 'The argument of tnot/1 is not tabled: ~p'-[Pred] ].
  263permission_error(Action, Type, Object) -->
  264    [ 'No permission to ~w ~w `~p'''-[Action, Type, Object] ].
  265
  266
  267unknown_proc_msg(_:(^)/2) -->
  268    !,
  269    unknown_proc_msg((^)/2).
  270unknown_proc_msg((^)/2) -->
  271    !,
  272    [nl, '  ^/2 can only appear as the 2nd argument of setof/3 and bagof/3'].
  273unknown_proc_msg((:-)/2) -->
  274    !,
  275    [nl, '  Rules must be loaded from a file'],
  276    faq('ToplevelMode').
  277unknown_proc_msg((=>)/2) -->
  278    !,
  279    [nl, '  Rules must be loaded from a file'],
  280    faq('ToplevelMode').
  281unknown_proc_msg((:-)/1) -->
  282    !,
  283    [nl, '  Directives must be loaded from a file'],
  284    faq('ToplevelMode').
  285unknown_proc_msg((?-)/1) -->
  286    !,
  287    [nl, '  ?- is the Prolog prompt'],
  288    faq('ToplevelMode').
  289unknown_proc_msg(Proc) -->
  290    { dwim_predicates(Proc, Dwims) },
  291    (   {Dwims \== []}
  292    ->  [nl, '  However, there are definitions for:', nl],
  293        dwim_message(Dwims)
  294    ;   []
  295    ).
  296
  297dependency_error(shared(Shared), private(Private)) -->
  298    [ 'Shared table for ~p may not depend on private ~p'-[Shared, Private] ].
  299dependency_error(Dep, monotonic(On)) -->
  300    { '$pi_head'(PI, Dep),
  301      '$pi_head'(MPI, On)
  302    },
  303    [ 'Dependent ~p on monotonic predicate ~p is not monotonic or incremental'-
  304      [PI, MPI]
  305    ].
  306
  307faq(Page) -->
  308    [nl, '  See FAQ at https://www.swi-prolog.org/FAQ/', Page, '.txt' ].
  309
  310type_error_comment(_Expected, Actual) -->
  311    { type_of(Actual, Type),
  312      (   sub_atom(Type, 0, 1, _, First),
  313          memberchk(First, [a,e,i,o,u])
  314      ->  Article = an
  315      ;   Article = a
  316      )
  317    },
  318    [ ' (~w ~w)'-[Article, Type] ].
  319
  320type_of(Term, Type) :-
  321    (   attvar(Term)      -> Type = attvar
  322    ;   var(Term)         -> Type = var
  323    ;   atom(Term)        -> Type = atom
  324    ;   integer(Term)     -> Type = integer
  325    ;   string(Term)      -> Type = string
  326    ;   Term == []        -> Type = empty_list
  327    ;   blob(Term, BlobT) -> blob_type(BlobT, Type)
  328    ;   rational(Term)    -> Type = rational
  329    ;   float(Term)       -> Type = float
  330    ;   is_stream(Term)   -> Type = stream
  331    ;   is_dict(Term)     -> Type = dict
  332    ;   is_list(Term)     -> Type = list
  333    ;   cyclic_term(Term) -> Type = cyclic
  334    ;   compound(Term)    -> Type = compound
  335    ;                        Type = unknown
  336    ).
  337
  338blob_type(BlobT, Type) :-
  339    atom_concat(BlobT, '_reference', Type).
  340
  341syntax_error(end_of_clause) -->
  342    [ 'Unexpected end of clause' ].
  343syntax_error(end_of_clause_expected) -->
  344    [ 'End of clause expected' ].
  345syntax_error(end_of_file) -->
  346    [ 'Unexpected end of file' ].
  347syntax_error(end_of_file_in_block_comment) -->
  348    [ 'End of file in /* ... */ comment' ].
  349syntax_error(end_of_file_in_quoted(Quote)) -->
  350    [ 'End of file in quoted ' ],
  351    quoted_type(Quote).
  352syntax_error(illegal_number) -->
  353    [ 'Illegal number' ].
  354syntax_error(long_atom) -->
  355    [ 'Atom too long (see style_check/1)' ].
  356syntax_error(long_string) -->
  357    [ 'String too long (see style_check/1)' ].
  358syntax_error(operator_clash) -->
  359    [ 'Operator priority clash' ].
  360syntax_error(operator_expected) -->
  361    [ 'Operator expected' ].
  362syntax_error(operator_balance) -->
  363    [ 'Unbalanced operator' ].
  364syntax_error(quoted_punctuation) -->
  365    [ 'Operand expected, unquoted comma or bar found' ].
  366syntax_error(list_rest) -->
  367    [ 'Unexpected comma or bar in rest of list' ].
  368syntax_error(cannot_start_term) -->
  369    [ 'Illegal start of term' ].
  370syntax_error(punct(Punct, End)) -->
  371    [ 'Unexpected `~w\' before `~w\''-[Punct, End] ].
  372syntax_error(undefined_char_escape(C)) -->
  373    [ 'Unknown character escape in quoted atom or string: `\\~w\''-[C] ].
  374syntax_error(void_not_allowed) -->
  375    [ 'Empty argument list "()"' ].
  376syntax_error(Message) -->
  377    [ '~w'-[Message] ].
  378
  379quoted_type('\'') --> [atom].
  380quoted_type('\"') --> { current_prolog_flag(double_quotes, Type) }, [Type-[]].
  381quoted_type('\`') --> { current_prolog_flag(back_quotes, Type) }, [Type-[]].
  382
  383domain(range(Low,High)) -->
  384    !,
  385    ['[~q..~q]'-[Low,High] ].
  386domain(Domain) -->
  387    ['`~w\''-[Domain] ].
 tabling_existence_error(+Ball, +Context)//
Called on invalid shift/1 calls. Track those that result from tabling errors.
  394tabling_existence_error(Ball, Context) -->
  395    { table_shift_ball(Ball) },
  396    [ 'Tabling dependency error' ],
  397    swi_extra(Context).
  398
  399table_shift_ball(dependency(_Head)).
  400table_shift_ball(dependency(_Skeleton, _Trie, _Mono)).
  401table_shift_ball(call_info(_Skeleton, _Status)).
  402table_shift_ball(call_info(_GenSkeleton, _Skeleton, _Status)).
 dwim_predicates(+PI, -Dwims)
Find related predicate indicators.
  408dwim_predicates(Module:Name/_Arity, Dwims) :-
  409    !,
  410    findall(Dwim, dwim_predicate(Module:Name, Dwim), Dwims).
  411dwim_predicates(Name/_Arity, Dwims) :-
  412    findall(Dwim, dwim_predicate(user:Name, Dwim), Dwims).
  413
  414dwim_message([]) --> [].
  415dwim_message([M:Head|T]) -->
  416    { hidden_module(M),
  417      !,
  418      functor(Head, Name, Arity)
  419    },
  420    [ '        ~q'-[Name/Arity], nl ],
  421    dwim_message(T).
  422dwim_message([Module:Head|T]) -->
  423    !,
  424    { functor(Head, Name, Arity)
  425    },
  426    [ '        ~q'-[Module:Name/Arity], nl],
  427    dwim_message(T).
  428dwim_message([Head|T]) -->
  429    {functor(Head, Name, Arity)},
  430    [ '        ~q'-[Name/Arity], nl],
  431    dwim_message(T).
  432
  433
  434swi_message(io_error(Op, Stream)) -->
  435    [ 'I/O error in ~w on stream ~p'-[Op, Stream] ].
  436swi_message(thread_error(TID, false)) -->
  437    [ 'Thread ~p died due to failure:'-[TID] ].
  438swi_message(thread_error(TID, exception(Error))) -->
  439    [ 'Thread ~p died abnormally:'-[TID], nl ],
  440    translate_message(Error).
  441swi_message(dependency_error(Tabled, DependsOn)) -->
  442    dependency_error(Tabled, DependsOn).
  443swi_message(shell(execute, Cmd)) -->
  444    [ 'Could not execute `~w'''-[Cmd] ].
  445swi_message(shell(signal(Sig), Cmd)) -->
  446    [ 'Caught signal ~d on `~w'''-[Sig, Cmd] ].
  447swi_message(format(Fmt, Args)) -->
  448    [ Fmt-Args ].
  449swi_message(signal(Name, Num)) -->
  450    [ 'Caught signal ~d (~w)'-[Num, Name] ].
  451swi_message(limit_exceeded(Limit, MaxVal)) -->
  452    [ 'Exceeded ~w limit (~w)'-[Limit, MaxVal] ].
  453swi_message(goal_failed(Goal)) -->
  454    [ 'goal unexpectedly failed: ~p'-[Goal] ].
  455swi_message(shared_object(_Action, Message)) --> % Message = dlerror()
  456    [ '~w'-[Message] ].
  457swi_message(system_error(Error)) -->
  458    [ 'error in system call: ~w'-[Error]
  459    ].
  460swi_message(system_error) -->
  461    [ 'error in system call'
  462    ].
  463swi_message(failure_error(Goal)) -->
  464    [ 'Goal failed: ~p'-[Goal] ].
  465swi_message(timeout_error(Op, Stream)) -->
  466    [ 'Timeout in ~w from ~p'-[Op, Stream] ].
  467swi_message(not_implemented(Type, What)) -->
  468    [ '~w `~p\' is not implemented in this version'-[Type, What] ].
  469swi_message(context_error(nodirective, Goal)) -->
  470    { goal_to_predicate_indicator(Goal, PI) },
  471    [ 'Wrong context: ~p can only be used in a directive'-[PI] ].
  472swi_message(context_error(edit, no_default_file)) -->
  473    (   { current_prolog_flag(windows, true) }
  474    ->  [ 'Edit/0 can only be used after opening a \c
  475               Prolog file by double-clicking it' ]
  476    ;   [ 'Edit/0 can only be used with the "-s file" commandline option'
  477        ]
  478    ),
  479    [ nl, 'Use "?- edit(Topic)." or "?- emacs."' ].
  480swi_message(context_error(function, meta_arg(S))) -->
  481    [ 'Functions are not (yet) supported for meta-arguments of type ~q'-[S] ].
  482swi_message(format_argument_type(Fmt, Arg)) -->
  483    [ 'Illegal argument to format sequence ~~~w: ~p'-[Fmt, Arg] ].
  484swi_message(format(Msg)) -->
  485    [ 'Format error: ~w'-[Msg] ].
  486swi_message(conditional_compilation_error(unterminated, Where)) -->
  487    [ 'Unterminated conditional compilation from '-[] ],
  488    cond_location(Where).
  489swi_message(conditional_compilation_error(no_if, What)) -->
  490    [ ':- ~w without :- if'-[What] ].
  491swi_message(duplicate_key(Key)) -->
  492    [ 'Duplicate key: ~p'-[Key] ].
  493swi_message(initialization_error(failed, Goal, File:Line)) -->
  494    !,
  495    [ '~w:~w: ~p: false'-[File, Line, Goal] ].
  496swi_message(initialization_error(Error, Goal, File:Line)) -->
  497    [ '~w:~w: ~p '-[File, Line, Goal] ],
  498    translate_message(Error).
  499swi_message(determinism_error(PI, det, Found, property)) -->
  500    (   { '$pi_head'(user:PI, Head),
  501          predicate_property(Head, det)
  502        }
  503    ->  [ 'Deterministic procedure ~p'-[PI] ]
  504    ;   [ 'Procedure ~p called from a deterministic procedure'-[PI] ]
  505    ),
  506    det_error(Found).
  507swi_message(determinism_error(PI, det, fail, guard)) -->
  508    [ 'Procedure ~p failed after $-guard'-[PI] ].
  509swi_message(determinism_error(PI, det, fail, guard_in_caller)) -->
  510    [ 'Procedure ~p failed after $-guard in caller'-[PI] ].
  511swi_message(determinism_error(Goal, det, fail, goal)) -->
  512    [ 'Goal ~p failed'-[Goal] ].
  513swi_message(determinism_error(Goal, det, nondet, goal)) -->
  514    [ 'Goal ~p succeeded with a choice point'-[Goal] ].
  515swi_message(qlf_format_error(File, Message)) -->
  516    [ '~w: Invalid QLF file: ~w'-[File, Message] ].
  517swi_message(goal_expansion_error(bound, Term)) -->
  518    [ 'Goal expansion bound a variable to ~p'-[Term] ].
  519
  520det_error(nondet) -->
  521    [ ' succeeded with a choicepoint'- [] ].
  522det_error(fail) -->
  523    [ ' failed'- [] ].
  524
  525
  526cond_location(File:Line) -->
  527    { file_base_name(File, Base) },
  528    [ '~w:~d'-[Base, Line] ].
 swi_location(+Term)// is det
Print location information for error(Formal, ImplDefined) from the ImplDefined term.
  535:- public swi_location//1.  536swi_location(X) -->
  537    { var(X) },
  538    !.
  539swi_location(Context) -->
  540    { message_lang(Lang) },
  541    prolog:message_location(Lang, Context),
  542    !.
  543swi_location(Context) -->
  544    prolog:message_location(Context),
  545    !.
  546swi_location(context(Caller, _Msg)) -->
  547    { ground(Caller) },
  548    !,
  549    caller(Caller).
  550swi_location(file(Path, Line, -1, _CharNo)) -->
  551    !,
  552    [ '~w:~d: '-[Path, Line] ].
  553swi_location(file(Path, Line, LinePos, _CharNo)) -->
  554    [ '~w:~d:~d: '-[Path, Line, LinePos] ].
  555swi_location(stream(Stream, Line, LinePos, CharNo)) -->
  556    (   { is_stream(Stream),
  557          stream_property(Stream, file_name(File))
  558        }
  559    ->  swi_location(file(File, Line, LinePos, CharNo))
  560    ;   [ 'Stream ~w:~d:~d '-[Stream, Line, LinePos] ]
  561    ).
  562swi_location(autoload(File:Line)) -->
  563    [ '~w:~w: '-[File, Line] ].
  564swi_location(_) -->
  565    [].
  566
  567caller(system:'$record_clause'/3) -->
  568    !,
  569    [].
  570caller(Module:Name/Arity) -->
  571    !,
  572    (   { \+ hidden_module(Module) }
  573    ->  [ '~q:~q/~w: '-[Module, Name, Arity] ]
  574    ;   [ '~q/~w: '-[Name, Arity] ]
  575    ).
  576caller(Name/Arity) -->
  577    [ '~q/~w: '-[Name, Arity] ].
  578caller(Caller) -->
  579    [ '~p: '-[Caller] ].
 swi_extra(+Term)// is det
Extract information from the second argument of an error(Formal, ImplDefined) that is printed after the core of the message.
See also
- swi_location//1 uses the same term to insert context before the core of the message.
  590swi_extra(X) -->
  591    { var(X) },
  592    !,
  593    [].
  594swi_extra(Context) -->
  595    { message_lang(Lang) },
  596    prolog:message_context(Lang, Context),
  597    !.
  598swi_extra(Context) -->
  599    prolog:message_context(Context).
  600swi_extra(context(_, Msg)) -->
  601    { nonvar(Msg),
  602      Msg \== ''
  603    },
  604    !,
  605    swi_comment(Msg).
  606swi_extra(string(String, CharPos)) -->
  607    { sub_string(String, 0, CharPos, _, Before),
  608      sub_string(String, CharPos, _, 0, After)
  609    },
  610    [ nl, '~w'-[Before], nl, '** here **', nl, '~w'-[After] ].
  611swi_extra(_) -->
  612    [].
  613
  614swi_comment(already_from(Module)) -->
  615    !,
  616    [ ' (already imported from ~q)'-[Module] ].
  617swi_comment(directory(_Dir)) -->
  618    !,
  619    [ ' (is a directory)' ].
  620swi_comment(not_a_directory(_Dir)) -->
  621    !,
  622    [ ' (is not a directory)' ].
  623swi_comment(Msg) -->
  624    [ ' (~w)'-[Msg] ].
  625
  626
  627thread_context -->
  628    { thread_self(Me), Me \== main, thread_property(Me, id(Id)) },
  629    !,
  630    ['[Thread ~w] '-[Id]].
  631thread_context -->
  632    [].
  633
  634                 /*******************************
  635                 *        NORMAL MESSAGES       *
  636                 *******************************/
  637
  638prolog_message(welcome) -->
  639    [ 'Welcome to SWI-Prolog (' ],
  640    prolog_message(threads),
  641    prolog_message(address_bits),
  642    ['version ' ],
  643    prolog_message(version),
  644    [ ')', nl ],
  645    prolog_message(copyright),
  646    [ nl ],
  647    translate_message(user_versions),
  648    [ nl ],
  649    prolog_message(documentaton),
  650    [ nl, nl ].
  651prolog_message(user_versions) -->
  652    (   { findall(Msg, prolog:version_msg(Msg), Msgs),
  653          Msgs \== []
  654        }
  655    ->  [nl],
  656        user_version_messages(Msgs)
  657    ;   []
  658    ).
  659prolog_message(deprecated(Term)) -->
  660    { nonvar(Term) },
  661    (   { message_lang(Lang) },
  662        prolog:deprecated(Lang, Term)
  663    ->  []
  664    ;   prolog:deprecated(Term)
  665    ->  []
  666    ;   deprecated(Term)
  667    ).
  668prolog_message(unhandled_exception(E)) -->
  669    { nonvar(E) },
  670    [ 'Unhandled exception: ' ],
  671    (   translate_message(E)
  672    ->  []
  673    ;   [ '~p'-[E] ]
  674    ).
 prolog_message(+Term)//
  678prolog_message(initialization_error(_, E, File:Line)) -->
  679    !,
  680    [ '~w:~d: '-[File, Line],
  681      'Initialization goal raised exception:', nl
  682    ],
  683    translate_message(E).
  684prolog_message(initialization_error(Goal, E, _)) -->
  685    [ 'Initialization goal ~p raised exception:'-[Goal], nl ],
  686    translate_message(E).
  687prolog_message(initialization_failure(_Goal, File:Line)) -->
  688    !,
  689    [ '~w:~d: '-[File, Line],
  690      'Initialization goal failed'-[]
  691    ].
  692prolog_message(initialization_failure(Goal, _)) -->
  693    [ 'Initialization goal failed: ~p'-[Goal]
  694    ].
  695prolog_message(initialization_exception(E)) -->
  696    [ 'Prolog initialisation failed:', nl ],
  697    translate_message(E).
  698prolog_message(init_goal_syntax(Error, Text)) -->
  699    !,
  700    [ '-g ~w: '-[Text] ],
  701    translate_message(Error).
  702prolog_message(init_goal_failed(failed, @(Goal,File:Line))) -->
  703    !,
  704    [ '~w:~w: ~p: false'-[File, Line, Goal] ].
  705prolog_message(init_goal_failed(Error, @(Goal,File:Line))) -->
  706    !,
  707    [ '~w:~w: ~p '-[File, Line, Goal] ],
  708    translate_message(Error).
  709prolog_message(init_goal_failed(failed, Text)) -->
  710    !,
  711    [ '-g ~w: false'-[Text] ].
  712prolog_message(init_goal_failed(Error, Text)) -->
  713    !,
  714    [ '-g ~w: '-[Text] ],
  715    translate_message(Error).
  716prolog_message(goal_failed(Context, Goal)) -->
  717    [ 'Goal (~w) failed: ~p'-[Context, Goal] ].
  718prolog_message(no_current_module(Module)) -->
  719    [ '~w is not a current module (created)'-[Module] ].
  720prolog_message(commandline_arg_type(Flag, Arg)) -->
  721    [ 'Bad argument to commandline option -~w: ~w'-[Flag, Arg] ].
  722prolog_message(missing_feature(Name)) -->
  723    [ 'This version of SWI-Prolog does not support ~w'-[Name] ].
  724prolog_message(singletons(_Term, List)) -->
  725    [ 'Singleton variables: ~w'-[List] ].
  726prolog_message(multitons(_Term, List)) -->
  727    [ 'Singleton-marked variables appearing more than once: ~w'-[List] ].
  728prolog_message(profile_no_cpu_time) -->
  729    [ 'No CPU-time info.  Check the SWI-Prolog manual for details' ].
  730prolog_message(non_ascii(Text, Type)) -->
  731    [ 'Unquoted ~w with non-portable characters: ~w'-[Type, Text] ].
  732prolog_message(io_warning(Stream, Message)) -->
  733    { stream_property(Stream, position(Position)),
  734      !,
  735      stream_position_data(line_count, Position, LineNo),
  736      stream_position_data(line_position, Position, LinePos),
  737      (   stream_property(Stream, file_name(File))
  738      ->  Obj = File
  739      ;   Obj = Stream
  740      )
  741    },
  742    [ '~p:~d:~d: ~w'-[Obj, LineNo, LinePos, Message] ].
  743prolog_message(io_warning(Stream, Message)) -->
  744    [ 'stream ~p: ~w'-[Stream, Message] ].
  745prolog_message(option_usage(pldoc)) -->
  746    [ 'Usage: --pldoc[=port]' ].
  747prolog_message(interrupt(begin)) -->
  748    [ 'Action (h for help) ? ', flush ].
  749prolog_message(interrupt(end)) -->
  750    [ 'continue' ].
  751prolog_message(interrupt(trace)) -->
  752    [ 'continue (trace mode)' ].
  753prolog_message(unknown_in_module_user) -->
  754    [ 'Using a non-error value for unknown in the global module', nl,
  755      'causes most of the development environment to stop working.', nl,
  756      'Please use :- dynamic or limit usage of unknown to a module.', nl,
  757      'See https://www.swi-prolog.org/howto/database.html'
  758    ].
  759prolog_message(untable(PI)) -->
  760    [ 'Reconsult: removed tabling for ~p'-[PI] ].
  761
  762
  763                 /*******************************
  764                 *         LOADING FILES        *
  765                 *******************************/
  766
  767prolog_message(modify_active_procedure(Who, What)) -->
  768    [ '~p: modified active procedure ~p'-[Who, What] ].
  769prolog_message(load_file(failed(user:File))) -->
  770    [ 'Failed to load ~p'-[File] ].
  771prolog_message(load_file(failed(Module:File))) -->
  772    [ 'Failed to load ~p into module ~p'-[File, Module] ].
  773prolog_message(load_file(failed(File))) -->
  774    [ 'Failed to load ~p'-[File] ].
  775prolog_message(mixed_directive(Goal)) -->
  776    [ 'Cannot pre-compile mixed load/call directive: ~p'-[Goal] ].
  777prolog_message(cannot_redefine_comma) -->
  778    [ 'Full stop in clause-body?  Cannot redefine ,/2' ].
  779prolog_message(illegal_autoload_index(Dir, Term)) -->
  780    [ 'Illegal term in INDEX file of directory ~w: ~w'-[Dir, Term] ].
  781prolog_message(redefined_procedure(Type, Proc)) -->
  782    [ 'Redefined ~w procedure ~p'-[Type, Proc] ],
  783    defined_definition('Previously defined', Proc).
  784prolog_message(declare_module(Module, abolish(Predicates))) -->
  785    [ 'Loading module ~w abolished: ~p'-[Module, Predicates] ].
  786prolog_message(import_private(Module, Private)) -->
  787    [ 'import/1: ~p is not exported (still imported into ~q)'-
  788      [Private, Module]
  789    ].
  790prolog_message(ignored_weak_import(Into, From:PI)) -->
  791    [ 'Local definition of ~p overrides weak import from ~q'-
  792      [Into:PI, From]
  793    ].
  794prolog_message(undefined_export(Module, PI)) -->
  795    [ 'Exported procedure ~q:~q is not defined'-[Module, PI] ].
  796prolog_message(no_exported_op(Module, Op)) -->
  797    [ 'Operator ~q:~q is not exported (still defined)'-[Module, Op] ].
  798prolog_message(discontiguous((-)/2,_)) -->
  799    prolog_message(minus_in_identifier).
  800prolog_message(discontiguous(Proc,Current)) -->
  801    [ 'Clauses of ', ansi(code, '~p', [Proc]),
  802      ' are not together in the source-file', nl ],
  803    current_definition(Proc, 'Earlier definition at '),
  804    [ 'Current predicate: ', ansi(code, '~p', [Current]), nl,
  805      'Use ', ansi(code, ':- discontiguous ~p.', [Proc]),
  806      ' to suppress this message'
  807    ].
  808prolog_message(decl_no_effect(Goal)) -->
  809    [ 'Deprecated declaration has no effect: ~p'-[Goal] ].
  810prolog_message(load_file(start(Level, File))) -->
  811    [ '~|~t~*+Loading '-[Level] ],
  812    load_file(File),
  813    [ ' ...' ].
  814prolog_message(include_file(start(Level, File))) -->
  815    [ '~|~t~*+include '-[Level] ],
  816    load_file(File),
  817    [ ' ...' ].
  818prolog_message(include_file(done(Level, File))) -->
  819    [ '~|~t~*+included '-[Level] ],
  820    load_file(File).
  821prolog_message(load_file(done(Level, File, Action, Module, Time, Clauses))) -->
  822    [ '~|~t~*+'-[Level] ],
  823    load_file(File),
  824    [ ' ~w'-[Action] ],
  825    load_module(Module),
  826    [ ' ~2f sec, ~D clauses'-[Time, Clauses] ].
  827prolog_message(dwim_undefined(Goal, Alternatives)) -->
  828    { goal_to_predicate_indicator(Goal, Pred)
  829    },
  830    [ 'Unknown procedure: ~q'-[Pred], nl,
  831      '    However, there are definitions for:', nl
  832    ],
  833    dwim_message(Alternatives).
  834prolog_message(dwim_correct(Into)) -->
  835    [ 'Correct to: ~q? '-[Into], flush ].
  836prolog_message(error(loop_error(Spec), file_search(Used))) -->
  837    [ 'File search: too many levels of indirections on: ~p'-[Spec], nl,
  838      '    Used alias expansions:', nl
  839    ],
  840    used_search(Used).
  841prolog_message(minus_in_identifier) -->
  842    [ 'The "-" character should not be used to separate words in an', nl,
  843      'identifier.  Check the SWI-Prolog FAQ for details.'
  844    ].
  845prolog_message(qlf(removed_after_error(File))) -->
  846    [ 'Removed incomplete QLF file ~w'-[File] ].
  847prolog_message(qlf(recompile(Spec,_Pl,_Qlf,Reason))) -->
  848    [ '~p: recompiling QLF file'-[Spec] ],
  849    qlf_recompile_reason(Reason).
  850prolog_message(qlf(can_not_recompile(Spec,QlfFile,_Reason))) -->
  851    [ '~p: can not recompile "~w" (access denied)'-[Spec, QlfFile], nl,
  852      '\tLoading from source'-[]
  853    ].
  854prolog_message(qlf(system_lib_out_of_date(Spec,QlfFile))) -->
  855    [ '~p: can not recompile "~w" (access denied)'-[Spec, QlfFile], nl,
  856      '\tLoading QlfFile'-[]
  857    ].
  858prolog_message(redefine_module(Module, OldFile, File)) -->
  859    [ 'Module "~q" already loaded from ~w.'-[Module, OldFile], nl,
  860      'Wipe and reload from ~w? '-[File], flush
  861    ].
  862prolog_message(redefine_module_reply) -->
  863    [ 'Please answer y(es), n(o) or a(bort)' ].
  864prolog_message(reloaded_in_module(Absolute, OldContext, LM)) -->
  865    [ '~w was previously loaded in module ~w'-[Absolute, OldContext], nl,
  866      '\tnow it is reloaded into module ~w'-[LM] ].
  867prolog_message(expected_layout(Expected, Pos)) -->
  868    [ 'Layout data: expected ~w, found: ~p'-[Expected, Pos] ].
  869
  870defined_definition(Message, Spec) -->
  871    { strip_module(user:Spec, M, Name/Arity),
  872      functor(Head, Name, Arity),
  873      predicate_property(M:Head, file(File)),
  874      predicate_property(M:Head, line_count(Line))
  875    },
  876    !,
  877    [ nl, '~w at ~w:~d'-[Message, File,Line] ].
  878defined_definition(_, _) --> [].
  879
  880used_search([]) -->
  881    [].
  882used_search([Alias=Expanded|T]) -->
  883    [ '        file_search_path(~p, ~p)'-[Alias, Expanded], nl ],
  884    used_search(T).
  885
  886load_file(file(Spec, _Path)) -->
  887    (   {atomic(Spec)}
  888    ->  [ '~w'-[Spec] ]
  889    ;   [ '~p'-[Spec] ]
  890    ).
  891%load_file(file(_, Path)) -->
  892%       [ '~w'-[Path] ].
  893
  894load_module(user) --> !.
  895load_module(system) --> !.
  896load_module(Module) -->
  897    [ ' into ~w'-[Module] ].
  898
  899goal_to_predicate_indicator(Goal, PI) :-
  900    strip_module(Goal, Module, Head),
  901    callable_name_arity(Head, Name, Arity),
  902    user_predicate_indicator(Module:Name/Arity, PI).
  903
  904callable_name_arity(Goal, Name, Arity) :-
  905    compound(Goal),
  906    !,
  907    compound_name_arity(Goal, Name, Arity).
  908callable_name_arity(Goal, Goal, 0) :-
  909    atom(Goal).
  910
  911user_predicate_indicator(Module:PI, PI) :-
  912    hidden_module(Module),
  913    !.
  914user_predicate_indicator(PI, PI).
  915
  916hidden_module(user) :- !.
  917hidden_module(system) :- !.
  918hidden_module(M) :-
  919    sub_atom(M, 0, _, _, $).
  920
  921current_definition(Proc, Prefix) -->
  922    { pi_uhead(Proc, Head),
  923      predicate_property(Head, file(File)),
  924      predicate_property(Head, line_count(Line))
  925    },
  926    [ '~w~w:~d'-[Prefix,File,Line], nl ].
  927current_definition(_, _) --> [].
  928
  929pi_uhead(Module:Name/Arity, Module:Head) :-
  930    !,
  931    atom(Module), atom(Name), integer(Arity),
  932    functor(Head, Name, Arity).
  933pi_uhead(Name/Arity, user:Head) :-
  934    atom(Name), integer(Arity),
  935    functor(Head, Name, Arity).
  936
  937qlf_recompile_reason(old) -->
  938    !,
  939    [ ' (out of date)'-[] ].
  940qlf_recompile_reason(_) -->
  941    [ ' (incompatible with current Prolog version)'-[] ].
  942
  943prolog_message(file_search(cache(Spec, _Cond), Path)) -->
  944    [ 'File search: ~p --> ~p (cache)'-[Spec, Path] ].
  945prolog_message(file_search(found(Spec, Cond), Path)) -->
  946    [ 'File search: ~p --> ~p OK ~p'-[Spec, Path, Cond] ].
  947prolog_message(file_search(tried(Spec, Cond), Path)) -->
  948    [ 'File search: ~p --> ~p NO ~p'-[Spec, Path, Cond] ].
  949
  950                 /*******************************
  951                 *              GC              *
  952                 *******************************/
  953
  954prolog_message(agc(start)) -->
  955    thread_context,
  956    [ 'AGC: ', flush ].
  957prolog_message(agc(done(Collected, Remaining, Time))) -->
  958    [ at_same_line,
  959      'reclaimed ~D atoms in ~3f sec. (remaining: ~D)'-
  960      [Collected, Time, Remaining]
  961    ].
  962prolog_message(cgc(start)) -->
  963    thread_context,
  964    [ 'CGC: ', flush ].
  965prolog_message(cgc(done(CollectedClauses, _CollectedBytes,
  966                        RemainingBytes, Time))) -->
  967    [ at_same_line,
  968      'reclaimed ~D clauses in ~3f sec. (pending: ~D bytes)'-
  969      [CollectedClauses, Time, RemainingBytes]
  970    ].
  971
  972		 /*******************************
  973		 *        STACK OVERFLOW	*
  974		 *******************************/
  975
  976out_of_stack(Context) -->
  977    { human_stack_size(Context.localused,   Local),
  978      human_stack_size(Context.globalused,  Global),
  979      human_stack_size(Context.trailused,   Trail),
  980      human_stack_size(Context.stack_limit, Limit),
  981      LCO is (100*(Context.depth - Context.environments))/Context.depth
  982    },
  983    [ 'Stack limit (~s) exceeded'-[Limit], nl,
  984      '  Stack sizes: local: ~s, global: ~s, trail: ~s'-[Local,Global,Trail], nl,
  985      '  Stack depth: ~D, last-call: ~0f%, Choice points: ~D'-
  986         [Context.depth, LCO, Context.choicepoints], nl
  987    ],
  988    overflow_reason(Context, Resolve),
  989    resolve_overflow(Resolve).
  990
  991human_stack_size(Size, String) :-
  992    Size < 100,
  993    format(string(String), '~dKb', [Size]).
  994human_stack_size(Size, String) :-
  995    Size < 100 000,
  996    Value is Size / 1024,
  997    format(string(String), '~1fMb', [Value]).
  998human_stack_size(Size, String) :-
  999    Value is Size / (1024*1024),
 1000    format(string(String), '~1fGb', [Value]).
 1001
 1002overflow_reason(Context, fix) -->
 1003    show_non_termination(Context),
 1004    !.
 1005overflow_reason(Context, enlarge) -->
 1006    { Stack = Context.get(stack) },
 1007    !,
 1008    [ '  In:'-[], nl ],
 1009    stack(Stack).
 1010overflow_reason(_Context, enlarge) -->
 1011    [ '  Insufficient global stack'-[] ].
 1012
 1013show_non_termination(Context) -->
 1014    (   { Stack = Context.get(cycle) }
 1015    ->  [ '  Probable infinite recursion (cycle):'-[], nl ]
 1016    ;   { Stack = Context.get(non_terminating) }
 1017    ->  [ '  Possible non-terminating recursion:'-[], nl ]
 1018    ),
 1019    stack(Stack).
 1020
 1021stack([]) --> [].
 1022stack([frame(Depth, M:Goal, _)|T]) -->
 1023    [ '    [~D] ~q:'-[Depth, M] ],
 1024    stack_goal(Goal),
 1025    [ nl ],
 1026    stack(T).
 1027
 1028stack_goal(Goal) -->
 1029    { compound(Goal),
 1030      !,
 1031      compound_name_arity(Goal, Name, Arity)
 1032    },
 1033    [ '~q('-[Name] ],
 1034    stack_goal_args(1, Arity, Goal),
 1035    [ ')'-[] ].
 1036stack_goal(Goal) -->
 1037    [ '~q'-[Goal] ].
 1038
 1039stack_goal_args(I, Arity, Goal) -->
 1040    { I =< Arity,
 1041      !,
 1042      arg(I, Goal, A),
 1043      I2 is I + 1
 1044    },
 1045    stack_goal_arg(A),
 1046    (   { I2 =< Arity }
 1047    ->  [ ', '-[] ],
 1048        stack_goal_args(I2, Arity, Goal)
 1049    ;   []
 1050    ).
 1051stack_goal_args(_, _, _) -->
 1052    [].
 1053
 1054stack_goal_arg(A) -->
 1055    { nonvar(A),
 1056      A = [Len|T],
 1057      !
 1058    },
 1059    (   {Len == cyclic_term}
 1060    ->  [ '[cyclic list]'-[] ]
 1061    ;   {T == []}
 1062    ->  [ '[length:~D]'-[Len] ]
 1063    ;   [ '[length:~D|~p]'-[Len, T] ]
 1064    ).
 1065stack_goal_arg(A) -->
 1066    { nonvar(A),
 1067      A = _/_,
 1068      !
 1069    },
 1070    [ '<compound ~p>'-[A] ].
 1071stack_goal_arg(A) -->
 1072    [ '~p'-[A] ].
 1073
 1074resolve_overflow(fix) -->
 1075    [].
 1076resolve_overflow(enlarge) -->
 1077    { current_prolog_flag(stack_limit, LimitBytes),
 1078      NewLimit is LimitBytes * 2
 1079    },
 1080    [ nl,
 1081      'Use the --stack_limit=size[KMG] command line option or'-[], nl,
 1082      '?- set_prolog_flag(stack_limit, ~I). to double the limit.'-[NewLimit]
 1083    ].
 1084
 1085
 1086                 /*******************************
 1087                 *        MAKE/AUTOLOAD         *
 1088                 *******************************/
 1089
 1090prolog_message(make(reload(Files))) -->
 1091    { length(Files, N)
 1092    },
 1093    [ 'Make: reloading ~D files'-[N] ].
 1094prolog_message(make(done(_Files))) -->
 1095    [ 'Make: finished' ].
 1096prolog_message(make(library_index(Dir))) -->
 1097    [ 'Updating index for library ~w'-[Dir] ].
 1098prolog_message(autoload(Pred, File)) -->
 1099    thread_context,
 1100    [ 'autoloading ~p from ~w'-[Pred, File] ].
 1101prolog_message(autoload(read_index(Dir))) -->
 1102    [ 'Loading autoload index for ~w'-[Dir] ].
 1103prolog_message(autoload(disabled(Loaded))) -->
 1104    [ 'Disabled autoloading (loaded ~D files)'-[Loaded] ].
 1105prolog_message(autoload(already_defined(PI, From))) -->
 1106    [ ansi(code, '~p', [PI]) ],
 1107    (   { '$pi_head'(PI, Head),
 1108          predicate_property(Head, built_in)
 1109        }
 1110    ->  [' is a built-in predicate']
 1111    ;   [ ' is already imported from module ',
 1112          ansi(code, '~p', [From])
 1113        ]
 1114    ).
 1115
 1116swi_message(autoload(Msg)) -->
 1117    [ nl, '  ' ],
 1118    autoload_message(Msg).
 1119
 1120autoload_message(not_exported(PI, Spec, _FullFile, _Exports)) -->
 1121    [ ansi(code, '~w', [Spec]),
 1122      ' does not export ',
 1123      ansi(code, '~p', [PI])
 1124    ].
 1125autoload_message(no_file(Spec)) -->
 1126    [ ansi(code, '~p', [Spec]), ': No such file' ].
 1127
 1128
 1129                 /*******************************
 1130                 *       COMPILER WARNINGS      *
 1131                 *******************************/
 1132
 1133% print warnings about dubious code raised by the compiler.
 1134% TBD: pass in PC to produce exact error locations.
 1135
 1136prolog_message(compiler_warnings(Clause, Warnings0)) -->
 1137    {   print_goal_options(DefOptions),
 1138        (   prolog_load_context(variable_names, VarNames)
 1139        ->  warnings_with_named_vars(Warnings0, VarNames, Warnings),
 1140            Options = [variable_names(VarNames)|DefOptions]
 1141        ;   Options = DefOptions,
 1142            Warnings = Warnings0
 1143        )
 1144    },
 1145    compiler_warnings(Warnings, Clause, Options).
 1146
 1147warnings_with_named_vars([], _, []).
 1148warnings_with_named_vars([H|T0], VarNames, [H|T]) :-
 1149    term_variables(H, Vars),
 1150    '$member'(V1, Vars),
 1151    '$member'(_=V2, VarNames),
 1152    V1 == V2,
 1153    !,
 1154    warnings_with_named_vars(T0, VarNames, T).
 1155warnings_with_named_vars([_|T0], VarNames, T) :-
 1156    warnings_with_named_vars(T0, VarNames, T).
 1157
 1158
 1159compiler_warnings([], _, _) --> [].
 1160compiler_warnings([H|T], Clause, Options) -->
 1161    (   compiler_warning(H, Clause, Options)
 1162    ->  []
 1163    ;   [ 'Unknown compiler warning: ~W'-[H,Options] ]
 1164    ),
 1165    (   {T==[]}
 1166    ->  []
 1167    ;   [nl]
 1168    ),
 1169    compiler_warnings(T, Clause, Options).
 1170
 1171compiler_warning(eq_vv(A,B), _Clause, Options) -->
 1172    (   { A == B }
 1173    ->  [ 'Test is always true: ~W'-[A==B, Options] ]
 1174    ;   [ 'Test is always false: ~W'-[A==B, Options] ]
 1175    ).
 1176compiler_warning(eq_singleton(A,B), _Clause, Options) -->
 1177    [ 'Test is always false: ~W'-[A==B, Options] ].
 1178compiler_warning(neq_vv(A,B), _Clause, Options) -->
 1179    (   { A \== B }
 1180    ->  [ 'Test is always true: ~W'-[A\==B, Options] ]
 1181    ;   [ 'Test is always false: ~W'-[A\==B, Options] ]
 1182    ).
 1183compiler_warning(neq_singleton(A,B), _Clause, Options) -->
 1184    [ 'Test is always true: ~W'-[A\==B, Options] ].
 1185compiler_warning(unify_singleton(A,B), _Clause, Options) -->
 1186    [ 'Unified variable is not used: ~W'-[A=B, Options] ].
 1187compiler_warning(always(Bool, Pred, Arg), _Clause, Options) -->
 1188    { Goal =.. [Pred,Arg] },
 1189    [ 'Test is always ~w: ~W'-[Bool, Goal, Options] ].
 1190compiler_warning(unbalanced_var(V), _Clause, Options) -->
 1191    [ 'Variable not introduced in all branches: ~W'-[V, Options] ].
 1192compiler_warning(branch_singleton(V), _Clause, Options) -->
 1193    [ 'Singleton variable in branch: ~W'-[V, Options] ].
 1194compiler_warning(negation_singleton(V), _Clause, Options) -->
 1195    [ 'Singleton variable in \\+: ~W'-[V, Options] ].
 1196compiler_warning(multiton(V), _Clause, Options) -->
 1197    [ 'Singleton-marked variable appears more than once: ~W'-[V, Options] ].
 1198
 1199print_goal_options(
 1200    [ quoted(true),
 1201      portray(true)
 1202    ]).
 1203
 1204
 1205                 /*******************************
 1206                 *      TOPLEVEL MESSAGES       *
 1207                 *******************************/
 1208
 1209prolog_message(version) -->
 1210    { current_prolog_flag(version_git, Version) },
 1211    !,
 1212    [ '~w'-[Version] ].
 1213prolog_message(version) -->
 1214    { current_prolog_flag(version_data, swi(Major,Minor,Patch,Options))
 1215    },
 1216    (   { memberchk(tag(Tag), Options) }
 1217    ->  [ '~w.~w.~w-~w'-[Major, Minor, Patch, Tag] ]
 1218    ;   [ '~w.~w.~w'-[Major, Minor, Patch] ]
 1219    ).
 1220prolog_message(address_bits) -->
 1221    { current_prolog_flag(address_bits, Bits)
 1222    },
 1223    !,
 1224    [ '~d bits, '-[Bits] ].
 1225prolog_message(threads) -->
 1226    { current_prolog_flag(threads, true)
 1227    },
 1228    !,
 1229    [ 'threaded, ' ].
 1230prolog_message(threads) -->
 1231    [].
 1232prolog_message(copyright) -->
 1233    [ 'SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.', nl,
 1234      'Please run ?- license. for legal details.'
 1235    ].
 1236prolog_message(documentaton) -->
 1237    [ 'For online help and background, visit https://www.swi-prolog.org', nl,
 1238      'For built-in help, use ?- help(Topic). or ?- apropos(Word).'
 1239    ].
 1240prolog_message(about) -->
 1241    [ 'SWI-Prolog version (' ],
 1242    prolog_message(threads),
 1243    prolog_message(address_bits),
 1244    ['version ' ],
 1245    prolog_message(version),
 1246    [ ')', nl ],
 1247    prolog_message(copyright).
 1248prolog_message(halt) -->
 1249    [ 'halt' ].
 1250prolog_message(break(begin, Level)) -->
 1251    [ 'Break level ~d'-[Level] ].
 1252prolog_message(break(end, Level)) -->
 1253    [ 'Exit break level ~d'-[Level] ].
 1254prolog_message(var_query(_)) -->
 1255    [ '... 1,000,000 ............ 10,000,000 years later', nl, nl,
 1256      '~t~8|>> 42 << (last release gives the question)'
 1257    ].
 1258prolog_message(close_on_abort(Stream)) -->
 1259    [ 'Abort: closed stream ~p'-[Stream] ].
 1260prolog_message(cancel_halt(Reason)) -->
 1261    [ 'Halt cancelled: ~p'-[Reason] ].
 1262prolog_message(on_error(halt(Status))) -->
 1263    { statistics(errors, Errors),
 1264      statistics(warnings, Warnings)
 1265    },
 1266    [ 'Halting with status ~w due to ~D errors and ~D warnings'-
 1267      [Status, Errors, Warnings] ].
 1268
 1269prolog_message(query(QueryResult)) -->
 1270    query_result(QueryResult).
 1271
 1272query_result(no) -->            % failure
 1273    [ ansi(truth(false), 'false.', []) ],
 1274    extra_line.
 1275query_result(yes(true, [])) -->      % prompt_alternatives_on: groundness
 1276    !,
 1277    [ ansi(truth(true), 'true.', []) ],
 1278    extra_line.
 1279query_result(yes(Delays, Residuals)) -->
 1280    result([], Delays, Residuals),
 1281    extra_line.
 1282query_result(done) -->          % user typed <CR>
 1283    extra_line.
 1284query_result(yes(Bindings, Delays, Residuals)) -->
 1285    result(Bindings, Delays, Residuals),
 1286    prompt(yes, Bindings, Delays, Residuals).
 1287query_result(more(Bindings, Delays, Residuals)) -->
 1288    result(Bindings, Delays, Residuals),
 1289    prompt(more, Bindings, Delays, Residuals).
 1290query_result(help) -->
 1291    [ nl, 'Actions:'-[], nl, nl,
 1292      '; (n, r, space, TAB): redo    t:          trace & redo'-[], nl,
 1293      'b:                    break   c (a, RET): exit'-[], nl,
 1294      'w:                    write   p           print'-[], nl,
 1295      'h (?):                help'-[],
 1296      nl, nl
 1297    ].
 1298query_result(action) -->
 1299    [ 'Action? '-[], flush ].
 1300query_result(confirm) -->
 1301    [ 'Please answer \'y\' or \'n\'? '-[], flush ].
 1302query_result(eof) -->
 1303    [ nl ].
 1304query_result(toplevel_open_line) -->
 1305    [].
 1306
 1307prompt(Answer, [], true, []-[]) -->
 1308    !,
 1309    prompt(Answer, empty).
 1310prompt(Answer, _, _, _) -->
 1311    !,
 1312    prompt(Answer, non_empty).
 1313
 1314prompt(yes, empty) -->
 1315    !,
 1316    [ ansi(truth(true), 'true.', []) ],
 1317    extra_line.
 1318prompt(yes, _) -->
 1319    !,
 1320    [ full_stop ],
 1321    extra_line.
 1322prompt(more, empty) -->
 1323    !,
 1324    [ ansi(truth(true), 'true ', []), flush ].
 1325prompt(more, _) -->
 1326    !,
 1327    [ ' '-[], flush ].
 1328
 1329result(Bindings, Delays, Residuals) -->
 1330    { current_prolog_flag(answer_write_options, Options0),
 1331      Options = [partial(true)|Options0],
 1332      GOptions = [priority(999)|Options0]
 1333    },
 1334    wfs_residual_program(Delays, GOptions),
 1335    bindings(Bindings, [priority(699)|Options]),
 1336    (   {Residuals == []-[]}
 1337    ->  bind_delays_sep(Bindings, Delays),
 1338        delays(Delays, GOptions)
 1339    ;   bind_res_sep(Bindings, Residuals),
 1340        residuals(Residuals, GOptions),
 1341        (   {Delays == true}
 1342        ->  []
 1343        ;   [','-[], nl],
 1344            delays(Delays, GOptions)
 1345        )
 1346    ).
 1347
 1348bindings([], _) -->
 1349    [].
 1350bindings([binding(Names,Skel,Subst)|T], Options) -->
 1351    { '$last'(Names, Name) },
 1352    var_names(Names), value(Name, Skel, Subst, Options),
 1353    (   { T \== [] }
 1354    ->  [ ','-[], nl ],
 1355        bindings(T, Options)
 1356    ;   []
 1357    ).
 1358
 1359var_names([Name]) -->
 1360    !,
 1361    [ '~w = '-[Name] ].
 1362var_names([Name1,Name2|T]) -->
 1363    !,
 1364    [ '~w = ~w, '-[Name1, Name2] ],
 1365    var_names([Name2|T]).
 1366
 1367
 1368value(Name, Skel, Subst, Options) -->
 1369    (   { var(Skel), Subst = [Skel=S] }
 1370    ->  { Skel = '$VAR'(Name) },
 1371        [ '~W'-[S, Options] ]
 1372    ;   [ '~W'-[Skel, Options] ],
 1373        substitution(Subst, Options)
 1374    ).
 1375
 1376substitution([], _) --> !.
 1377substitution([N=V|T], Options) -->
 1378    [ ', ', ansi(comment, '% where', []), nl,
 1379      '    ~w = ~W'-[N,V,Options] ],
 1380    substitutions(T, Options).
 1381
 1382substitutions([], _) --> [].
 1383substitutions([N=V|T], Options) -->
 1384    [ ','-[], nl, '    ~w = ~W'-[N,V,Options] ],
 1385    substitutions(T, Options).
 1386
 1387
 1388residuals(Normal-Hidden, Options) -->
 1389    residuals1(Normal, Options),
 1390    bind_res_sep(Normal, Hidden),
 1391    (   {Hidden == []}
 1392    ->  []
 1393    ;   [ansi(comment, '% with pending residual goals', []), nl]
 1394    ),
 1395    residuals1(Hidden, Options).
 1396
 1397residuals1([], _) -->
 1398    [].
 1399residuals1([G|Gs], Options) -->
 1400    (   { Gs \== [] }
 1401    ->  [ '~W,'-[G, Options], nl ],
 1402        residuals1(Gs, Options)
 1403    ;   [ '~W'-[G, Options] ]
 1404    ).
 1405
 1406wfs_residual_program(true, _Options) -->
 1407    !.
 1408wfs_residual_program(Goal, _Options) -->
 1409    { current_prolog_flag(toplevel_list_wfs_residual_program, true),
 1410      '$current_typein_module'(TypeIn),
 1411      (   current_predicate(delays_residual_program/2)
 1412      ->  true
 1413      ;   use_module(library(wfs), [delays_residual_program/2])
 1414      ),
 1415      delays_residual_program(TypeIn:Goal, TypeIn:Program),
 1416      Program \== []
 1417    },
 1418    !,
 1419    [ ansi(comment, '% WFS residual program', []), nl ],
 1420    [ ansi(wfs(residual_program), '~@', ['$messages':list_clauses(Program)]) ].
 1421wfs_residual_program(_, _) --> [].
 1422
 1423delays(true, _Options) -->
 1424    !.
 1425delays(Goal, Options) -->
 1426    { current_prolog_flag(toplevel_list_wfs_residual_program, true)
 1427    },
 1428    !,
 1429    [ ansi(truth(undefined), '~W', [Goal, Options]) ].
 1430delays(_, _Options) -->
 1431    [ ansi(truth(undefined), undefined, []) ].
 1432
 1433:- public list_clauses/1. 1434
 1435list_clauses([]).
 1436list_clauses([H|T]) :-
 1437    (   system_undefined(H)
 1438    ->  true
 1439    ;   portray_clause(user_output, H, [indent(4)])
 1440    ),
 1441    list_clauses(T).
 1442
 1443system_undefined((undefined :- tnot(undefined))).
 1444system_undefined((answer_count_restraint :- tnot(answer_count_restraint))).
 1445system_undefined((radial_restraint :- tnot(radial_restraint))).
 1446
 1447bind_res_sep(_, []) --> !.
 1448bind_res_sep(_, []-[]) --> !.
 1449bind_res_sep([], _) --> !.
 1450bind_res_sep(_, _) --> [','-[], nl].
 1451
 1452bind_delays_sep([], _) --> !.
 1453bind_delays_sep(_, true) --> !.
 1454bind_delays_sep(_, _) --> [','-[], nl].
 1455
 1456extra_line -->
 1457    { current_prolog_flag(toplevel_extra_white_line, true) },
 1458    !,
 1459    ['~N'-[]].
 1460extra_line -->
 1461    [].
 1462
 1463prolog_message(if_tty(Message)) -->
 1464    (   {current_prolog_flag(tty_control, true)}
 1465    ->  [ at_same_line | Message ]
 1466    ;   []
 1467    ).
 1468prolog_message(halt(Reason)) -->
 1469    [ '~w: halt'-[Reason] ].
 1470prolog_message(no_action(Char)) -->
 1471    [ 'Unknown action: ~c (h for help)'-[Char], nl ].
 1472
 1473prolog_message(history(help(Show, Help))) -->
 1474    [ 'History Commands:', nl,
 1475      '    !!.              Repeat last query', nl,
 1476      '    !nr.             Repeat query numbered <nr>', nl,
 1477      '    !str.            Repeat last query starting with <str>', nl,
 1478      '    !?str.           Repeat last query holding <str>', nl,
 1479      '    ^old^new.        Substitute <old> into <new> of last query', nl,
 1480      '    !nr^old^new.     Substitute in query numbered <nr>', nl,
 1481      '    !str^old^new.    Substitute in query starting with <str>', nl,
 1482      '    !?str^old^new.   Substitute in query holding <str>', nl,
 1483      '    ~w.~21|Show history list'-[Show], nl,
 1484      '    ~w.~21|Show this list'-[Help], nl, nl
 1485    ].
 1486prolog_message(history(no_event)) -->
 1487    [ '! No such event' ].
 1488prolog_message(history(bad_substitution)) -->
 1489    [ '! Bad substitution' ].
 1490prolog_message(history(expanded(Event))) -->
 1491    [ '~w.'-[Event] ].
 1492prolog_message(history(history(Events))) -->
 1493    history_events(Events).
 1494
 1495history_events([]) -->
 1496    [].
 1497history_events([Nr/Event|T]) -->
 1498    [ '~t~w   ~8|~W~W'-[ Nr,
 1499                         Event, [partial(true)],
 1500                         '.', [partial(true)]
 1501                       ],
 1502      nl
 1503    ],
 1504    history_events(T).
 user_version_messages(+Terms)//
Helper for the welcome message to print information registered using version/1.
 1512user_version_messages([]) --> [].
 1513user_version_messages([H|T]) -->
 1514    user_version_message(H),
 1515    user_version_messages(T).
 user_version_message(+Term)
 1519user_version_message(Term) -->
 1520    translate_message(Term), !, [nl].
 1521user_version_message(Atom) -->
 1522    [ '~w'-[Atom], nl ].
 1523
 1524
 1525                 /*******************************
 1526                 *       DEBUGGER MESSAGES      *
 1527                 *******************************/
 1528
 1529prolog_message(spy(Head)) -->
 1530    { goal_to_predicate_indicator(Head, Pred)
 1531    },
 1532    [ 'Spy point on ~p'-[Pred] ].
 1533prolog_message(nospy(Head)) -->
 1534    { goal_to_predicate_indicator(Head, Pred)
 1535    },
 1536    [ 'Spy point removed from ~p'-[Pred] ].
 1537prolog_message(trace_mode(OnOff)) -->
 1538    [ 'Trace mode switched to ~w'-[OnOff] ].
 1539prolog_message(debug_mode(OnOff)) -->
 1540    [ 'Debug mode switched to ~w'-[OnOff] ].
 1541prolog_message(debugging(OnOff)) -->
 1542    [ 'Debug mode is ~w'-[OnOff] ].
 1543prolog_message(spying([])) -->
 1544    !,
 1545    [ 'No spy points' ].
 1546prolog_message(spying(Heads)) -->
 1547    [ 'Spy points (see spy/1) on:', nl ],
 1548    predicate_list(Heads).
 1549prolog_message(trace(Head, [])) -->
 1550    !,
 1551    { goal_to_predicate_indicator(Head, Pred)
 1552    },
 1553    [ '        ~p: Not tracing'-[Pred], nl].
 1554prolog_message(trace(Head, Ports)) -->
 1555    { goal_to_predicate_indicator(Head, Pred)
 1556    },
 1557    [ '        ~p: ~w'-[Pred, Ports], nl].
 1558prolog_message(tracing([])) -->
 1559    !,
 1560    [ 'No traced predicates (see trace/1)' ].
 1561prolog_message(tracing(Heads)) -->
 1562    [ 'Trace points (see trace/1) on:', nl ],
 1563    tracing_list(Heads).
 1564
 1565predicate_list([]) -->                  % TBD: Share with dwim, etc.
 1566    [].
 1567predicate_list([H|T]) -->
 1568    { goal_to_predicate_indicator(H, Pred)
 1569    },
 1570    [ '        ~p'-[Pred], nl],
 1571    predicate_list(T).
 1572
 1573tracing_list([]) -->
 1574    [].
 1575tracing_list([trace(Head, Ports)|T]) -->
 1576    translate_message(trace(Head, Ports)),
 1577    tracing_list(T).
 1578
 1579prolog_message(frame(Frame, backtrace, _PC)) -->
 1580    !,
 1581    { prolog_frame_attribute(Frame, level, Level)
 1582    },
 1583    [ ansi(frame(level), '~t[~D] ~10|', [Level]) ],
 1584    frame_context(Frame),
 1585    frame_goal(Frame).
 1586prolog_message(frame(Frame, choice, PC)) -->
 1587    !,
 1588    prolog_message(frame(Frame, backtrace, PC)).
 1589prolog_message(frame(_, cut_call, _)) --> !, [].
 1590prolog_message(frame(Goal, trace(Port))) -->
 1591    !,
 1592    thread_context,
 1593    [ ' T ' ],
 1594    port(Port),
 1595    goal(Goal).
 1596prolog_message(frame(Goal, trace(Port, Id))) -->
 1597    !,
 1598    thread_context,
 1599    [ ' T ' ],
 1600    port(Port, Id),
 1601    goal(Goal).
 1602prolog_message(frame(Frame, Port, _PC)) -->
 1603    frame_flags(Frame),
 1604    port(Port),
 1605    frame_level(Frame),
 1606    frame_context(Frame),
 1607    frame_depth_limit(Port, Frame),
 1608    frame_goal(Frame),
 1609    [ flush ].
 1610
 1611frame_goal(Frame) -->
 1612    { prolog_frame_attribute(Frame, goal, Goal)
 1613    },
 1614    goal(Goal).
 1615
 1616goal(Goal0) -->
 1617    { clean_goal(Goal0, Goal),
 1618      current_prolog_flag(debugger_write_options, Options)
 1619    },
 1620    [ '~W'-[Goal, Options] ].
 1621
 1622frame_level(Frame) -->
 1623    { prolog_frame_attribute(Frame, level, Level)
 1624    },
 1625    [ '(~D) '-[Level] ].
 1626
 1627frame_context(Frame) -->
 1628    (   { current_prolog_flag(debugger_show_context, true),
 1629          prolog_frame_attribute(Frame, context_module, Context)
 1630        }
 1631    ->  [ '[~w] '-[Context] ]
 1632    ;   []
 1633    ).
 1634
 1635frame_depth_limit(fail, Frame) -->
 1636    { prolog_frame_attribute(Frame, depth_limit_exceeded, true)
 1637    },
 1638    !,
 1639    [ '[depth-limit exceeded] ' ].
 1640frame_depth_limit(_, _) -->
 1641    [].
 1642
 1643frame_flags(Frame) -->
 1644    { prolog_frame_attribute(Frame, goal, Goal),
 1645      (   predicate_property(Goal, transparent)
 1646      ->  T = '^'
 1647      ;   T = ' '
 1648      ),
 1649      (   predicate_property(Goal, spying)
 1650      ->  S = '*'
 1651      ;   S = ' '
 1652      )
 1653    },
 1654    [ '~w~w '-[T, S] ].
 1655
 1656% trace/1,2 context handling
 1657port(Port, _Id-Level) -->
 1658    [ '[~d] '-Level ],
 1659    port(Port).
 1660
 1661port(Port) -->
 1662    { port_name(Port, Name)
 1663    },
 1664    !,
 1665    [ ansi(port(Port), '~w: ', [Name]) ].
 1666
 1667port_name(call,      'Call').
 1668port_name(exit,      'Exit').
 1669port_name(fail,      'Fail').
 1670port_name(redo,      'Redo').
 1671port_name(unify,     'Unify').
 1672port_name(exception, 'Exception').
 1673
 1674clean_goal(M:Goal, Goal) :-
 1675    hidden_module(M),
 1676    !.
 1677clean_goal(M:Goal, Goal) :-
 1678    predicate_property(M:Goal, built_in),
 1679    !.
 1680clean_goal(Goal, Goal).
 1681
 1682
 1683                 /*******************************
 1684                 *        COMPATIBILITY         *
 1685                 *******************************/
 1686
 1687prolog_message(compatibility(renamed(Old, New))) -->
 1688    [ 'The predicate ~p has been renamed to ~p.'-[Old, New], nl,
 1689      'Please update your sources for compatibility with future versions.'
 1690    ].
 1691
 1692
 1693                 /*******************************
 1694                 *            THREADS           *
 1695                 *******************************/
 1696
 1697prolog_message(abnormal_thread_completion(Goal, exception(Ex))) -->
 1698    !,
 1699    [ 'Thread running "~p" died on exception: '-[Goal] ],
 1700    translate_message(Ex).
 1701prolog_message(abnormal_thread_completion(Goal, fail)) -->
 1702    [ 'Thread running "~p" died due to failure'-[Goal] ].
 1703prolog_message(threads_not_died(Running)) -->
 1704    [ 'The following threads wouldn\'t die: ~p'-[Running] ].
 1705
 1706
 1707                 /*******************************
 1708                 *             PACKS            *
 1709                 *******************************/
 1710
 1711prolog_message(pack(attached(Pack, BaseDir))) -->
 1712    [ 'Attached package ~w at ~q'-[Pack, BaseDir] ].
 1713prolog_message(pack(duplicate(Entry, OldDir, Dir))) -->
 1714    [ 'Package ~w already attached at ~q.'-[Entry,OldDir], nl,
 1715      '\tIgnoring version from ~q'- [Dir]
 1716    ].
 1717prolog_message(pack(no_arch(Entry, Arch))) -->
 1718    [ 'Package ~w: no binary for architecture ~w'-[Entry, Arch] ].
 1719
 1720                 /*******************************
 1721                 *             MISC             *
 1722                 *******************************/
 1723
 1724prolog_message(null_byte_in_path(Component)) -->
 1725    [ '0-byte in PATH component: ~p (skipped directory)'-[Component] ].
 1726prolog_message(invalid_tmp_dir(Dir, Reason)) -->
 1727    [ 'Cannot use ~p as temporary file directory: ~w'-[Dir, Reason] ].
 1728prolog_message(ambiguous_stream_pair(Pair)) -->
 1729    [ 'Ambiguous operation on stream pair ~p'-[Pair] ].
 1730prolog_message(backcomp(init_file_moved(FoundFile))) -->
 1731    { absolute_file_name(app_config('init.pl'), InitFile,
 1732                         [ file_errors(fail)
 1733                         ])
 1734    },
 1735    [ 'The location of the config file has moved'-[], nl,
 1736      '  from "~w"'-[FoundFile], nl,
 1737      '  to   "~w"'-[InitFile], nl,
 1738      '  See https://www.swi-prolog.org/modified/config-files.html'-[]
 1739    ].
 1740
 1741		 /*******************************
 1742		 *          DEPRECATED		*
 1743		 *******************************/
 1744
 1745deprecated(set_prolog_stack(_Stack,limit)) -->
 1746    [ 'set_prolog_stack/2: limit(Size) sets the combined limit.'-[], nl,
 1747      'See https://www.swi-prolog.org/changes/stack-limit.html'
 1748    ].
 1749
 1750		 /*******************************
 1751		 *           TRIPWIRES		*
 1752		 *******************************/
 1753
 1754tripwire_message(Wire, Context) -->
 1755    [ 'Trapped tripwire ~w for '-[Wire] ],
 1756    tripwire_context(Wire, Context).
 1757
 1758tripwire_context(_, ATrie) -->
 1759    { '$is_answer_trie'(ATrie, _),
 1760      !,
 1761      '$tabling':atrie_goal(ATrie, QGoal),
 1762      user_predicate_indicator(QGoal, Goal)
 1763    },
 1764    [ '~p'-[Goal] ].
 1765tripwire_context(_, Ctx) -->
 1766    [ '~p'-[Ctx] ].
 1767
 1768
 1769		 /*******************************
 1770		 *     INTERNATIONALIZATION	*
 1771		 *******************************/
 1772
 1773:- create_prolog_flag(message_language, default, []).
 message_lang(-Lang) is multi
True when Lang is a language id preferred for messages. Starts with the most specific language (e.g., nl_BE) and ends with en.
 1780message_lang(Lang) :-
 1781    current_message_lang(Lang0),
 1782    (   Lang0 == en
 1783    ->  Lang = en
 1784    ;   sub_atom(Lang0, 0, _, _, en_)
 1785    ->  longest_id(Lang0, Lang)
 1786    ;   (   longest_id(Lang0, Lang)
 1787        ;   Lang = en
 1788        )
 1789    ).
 1790
 1791longest_id(Lang, Id) :-
 1792    split_string(Lang, "_-", "", [H|Components]),
 1793    longest_prefix(Components, Taken),
 1794    atomic_list_concat([H|Taken], '_', Id).
 1795
 1796longest_prefix([H|T0], [H|T]) :-
 1797    longest_prefix(T0, T).
 1798longest_prefix(_, []).
 current_message_lang(-Lang) is det
Get the current language for messages.
 1804current_message_lang(Lang) :-
 1805    (   current_prolog_flag(message_language, Lang0),
 1806        Lang0 \== default
 1807    ->  Lang = Lang0
 1808    ;   os_user_lang(Lang0)
 1809    ->  clean_encoding(Lang0, Lang1),
 1810        set_prolog_flag(message_language, Lang1),
 1811        Lang = Lang1
 1812    ;   Lang = en
 1813    ).
 1814
 1815os_user_lang(Lang) :-
 1816    current_prolog_flag(windows, true),
 1817    win_get_user_preferred_ui_languages(name, [Lang|_]).
 1818os_user_lang(Lang) :-
 1819    catch(setlocale(messages, _, ''), _, fail),
 1820    setlocale(messages, Lang, Lang).
 1821os_user_lang(Lang) :-
 1822    getenv('LANG', Lang).
 1823
 1824
 1825clean_encoding(Lang0, Lang) :-
 1826    (   sub_atom(Lang0, A, _, _, '.')
 1827    ->  sub_atom(Lang0, 0, A, _, Lang)
 1828    ;   Lang = Lang0
 1829    ).
 1830
 1831
 1832		 /*******************************
 1833		 *        DEFAULT THEME		*
 1834		 *******************************/
 1835
 1836:- public default_theme/2. 1837
 1838default_theme(var,                    [fg(red)]).
 1839default_theme(code,                   [fg(blue)]).
 1840default_theme(comment,                [fg(green)]).
 1841default_theme(warning,                [fg(red)]).
 1842default_theme(error,                  [bold, fg(red)]).
 1843default_theme(truth(false),           [bold, fg(red)]).
 1844default_theme(truth(true),            [bold]).
 1845default_theme(truth(undefined),       [bold, fg(cyan)]).
 1846default_theme(wfs(residual_program),  [fg(cyan)]).
 1847default_theme(frame(level),           [bold]).
 1848default_theme(port(call),             [bold, fg(green)]).
 1849default_theme(port(exit),             [bold, fg(green)]).
 1850default_theme(port(fail),             [bold, fg(red)]).
 1851default_theme(port(redo),             [bold, fg(yellow)]).
 1852default_theme(port(unify),            [bold, fg(blue)]).
 1853default_theme(port(exception),        [bold, fg(magenta)]).
 1854default_theme(message(informational), [fg(green)]).
 1855default_theme(message(information),   [fg(green)]).
 1856default_theme(message(debug(_)),      [fg(blue)]).
 1857default_theme(message(Level),         Attrs) :-
 1858    nonvar(Level),
 1859    default_theme(Level, Attrs).
 1860
 1861
 1862                 /*******************************
 1863                 *      PRINTING MESSAGES       *
 1864                 *******************************/
 1865
 1866:- multifile
 1867    user:message_hook/3,
 1868    prolog:message_prefix_hook/2. 1869:- dynamic
 1870    user:message_hook/3,
 1871    prolog:message_prefix_hook/2. 1872:- thread_local
 1873    user:thread_message_hook/3. 1874:- '$hide'((push_msg/1,pop_msg/0)).
 print_message(+Kind, +Term)
Print an error message using a term as generated by the exception system.
 1881print_message(Level, Term) :-
 1882    setup_call_cleanup(
 1883        push_msg(Term),
 1884        print_message_guarded(Level, Term),
 1885        pop_msg),
 1886    !.
 1887print_message(Level, Term) :-
 1888    (   Level \== silent
 1889    ->  format(user_error, 'Recursive ~w message: ~q~n', [Level, Term])
 1890    ;   true
 1891    ).
 1892
 1893push_msg(Term) :-
 1894    nb_current('$inprint_message', Messages),
 1895    !,
 1896    \+ ( '$member'(Msg, Messages),
 1897         Msg =@= Term
 1898       ),
 1899    b_setval('$inprint_message', [Term|Messages]).
 1900push_msg(Term) :-
 1901    b_setval('$inprint_message', [Term]).
 1902
 1903pop_msg :-
 1904    (   nb_current('$inprint_message', [_|Messages]),
 1905        Messages \== []
 1906    ->  b_setval('$inprint_message', Messages)
 1907    ;   nb_delete('$inprint_message'),              % delete history
 1908        b_setval('$inprint_message', [])
 1909    ).
 1910
 1911print_message_guarded(Level, Term) :-
 1912    (   must_print(Level, Term)
 1913    ->  (   translate_message(Term, Lines, [])
 1914        ->  (   nonvar(Term),
 1915                (   notrace(user:thread_message_hook(Term, Level, Lines))
 1916                ->  true
 1917                ;   notrace(user:message_hook(Term, Level, Lines))
 1918                )
 1919            ->  true
 1920            ;   '$inc_message_count'(Level),
 1921                print_system_message(Term, Level, Lines),
 1922                maybe_halt_on_error(Level)
 1923            )
 1924        )
 1925    ;   true
 1926    ).
 1927
 1928maybe_halt_on_error(error) :-
 1929    current_prolog_flag(on_error, halt),
 1930    !,
 1931    halt(1).
 1932maybe_halt_on_error(warning) :-
 1933    current_prolog_flag(on_warning, halt),
 1934    !,
 1935    halt(1).
 1936maybe_halt_on_error(_).
 print_system_message(+Term, +Kind, +Lines)
Print the message if the user did not intecept the message. The first is used for errors and warnings that can be related to source-location. Note that syntax errors have their own source-location and should therefore not be handled this way.
 1946print_system_message(_, silent, _) :- !.
 1947print_system_message(_, informational, _) :-
 1948    current_prolog_flag(verbose, silent),
 1949    !.
 1950print_system_message(_, banner, _) :-
 1951    current_prolog_flag(verbose, silent),
 1952    !.
 1953print_system_message(_, _, []) :- !.
 1954print_system_message(Term, Kind, Lines) :-
 1955    catch(flush_output(user_output), _, true),      % may not exist
 1956    source_location(File, Line),
 1957    Term \= error(syntax_error(_), _),
 1958    msg_property(Kind, location_prefix(File:Line, LocPrefix, LinePrefix)),
 1959    !,
 1960    insert_prefix(Lines, LinePrefix, Ctx, PrefixLines),
 1961    '$append'([ begin(Kind, Ctx),
 1962                LocPrefix,
 1963                nl
 1964              | PrefixLines
 1965              ],
 1966              [ end(Ctx)
 1967              ],
 1968              AllLines),
 1969    msg_property(Kind, stream(Stream)),
 1970    ignore(stream_property(Stream, position(Pos))),
 1971    print_message_lines(Stream, AllLines),
 1972    (   \+ stream_property(Stream, position(Pos)),
 1973        msg_property(Kind, wait(Wait)),
 1974        Wait > 0
 1975    ->  sleep(Wait)
 1976    ;   true
 1977    ).
 1978print_system_message(_, Kind, Lines) :-
 1979    msg_property(Kind, stream(Stream)),
 1980    print_message_lines(Stream, kind(Kind), Lines).
 1981
 1982:- multifile
 1983    user:message_property/2. 1984
 1985msg_property(Kind, Property) :-
 1986    notrace(user:message_property(Kind, Property)),
 1987    !.
 1988msg_property(Kind, prefix(Prefix)) :-
 1989    msg_prefix(Kind, Prefix),
 1990    !.
 1991msg_property(_, prefix('~N')) :- !.
 1992msg_property(query, stream(user_output)) :- !.
 1993msg_property(_, stream(user_error)) :- !.
 1994msg_property(error, tag('ERROR')).
 1995msg_property(warning, tag('Warning')).
 1996msg_property(Level,
 1997             location_prefix(File:Line,
 1998                             Prefix1-[File,Line],
 1999                             PrefixC)) :-
 2000    include_msg_location(Level),
 2001    msg_property(Level, tag(Tag)),
 2002    atomics_to_string(['~N', Tag, ': ~w:~d:'], Prefix1),
 2003    atomics_to_string(['~N', Tag, ':    '  ], PrefixC).
 2004msg_property(error,   wait(0.1)) :- !.
 2005
 2006include_msg_location(warning).
 2007include_msg_location(error).
 2008
 2009msg_prefix(debug(_), Prefix) :-
 2010    msg_context('~N% ', Prefix).
 2011msg_prefix(Level, Prefix) :-
 2012    msg_property(Level, tag(Tag)),
 2013    atomics_to_string(['~N', Tag, ': '], Prefix0),
 2014    msg_context(Prefix0, Prefix).
 2015msg_prefix(informational, '~N% ').
 2016msg_prefix(information,   '~N% ').
 msg_context(+Prefix0, -Prefix) is det
Add contextual information to a message. This uses the Prolog flag message_context. Recognised context terms are:

In addition, the hook message_prefix_hook/2 is called that allows for additional context information.

 2030msg_context(Prefix0, Prefix) :-
 2031    current_prolog_flag(message_context, Context),
 2032    is_list(Context),
 2033    !,
 2034    add_message_context(Context, Prefix0, Prefix).
 2035msg_context(Prefix, Prefix).
 2036
 2037add_message_context([], Prefix, Prefix).
 2038add_message_context([H|T], Prefix0, Prefix) :-
 2039    (   add_message_context1(H, Prefix0, Prefix1)
 2040    ->  true
 2041    ;   Prefix1 = Prefix0
 2042    ),
 2043    add_message_context(T, Prefix1, Prefix).
 2044
 2045add_message_context1(Context, Prefix0, Prefix) :-
 2046    prolog:message_prefix_hook(Context, Extra),
 2047    atomics_to_string([Prefix0, Extra, ' '], Prefix).
 2048add_message_context1(time, Prefix0, Prefix) :-
 2049    get_time(Now),
 2050    format_time(string(S), '%T.%3f ', Now),
 2051    string_concat(Prefix0, S, Prefix).
 2052add_message_context1(time(Format), Prefix0, Prefix) :-
 2053    get_time(Now),
 2054    format_time(string(S), Format, Now),
 2055    atomics_to_string([Prefix0, S, ' '], Prefix).
 2056add_message_context1(thread, Prefix0, Prefix) :-
 2057    thread_self(Id0),
 2058    Id0 \== main,
 2059    !,
 2060    (   atom(Id0)
 2061    ->  Id = Id0
 2062    ;   thread_property(Id0, id(Id))
 2063    ),
 2064    format(string(Prefix), '~w[Thread ~w] ', [Prefix0, Id]).
 print_message_lines(+Stream, +PrefixOrKind, +Lines)
Quintus compatibility predicate to print message lines using a prefix.
 2071print_message_lines(Stream, kind(Kind), Lines) :-
 2072    !,
 2073    msg_property(Kind, prefix(Prefix)),
 2074    insert_prefix(Lines, Prefix, Ctx, PrefixLines),
 2075    '$append'([ begin(Kind, Ctx)
 2076              | PrefixLines
 2077              ],
 2078              [ end(Ctx)
 2079              ],
 2080              AllLines),
 2081    print_message_lines(Stream, AllLines).
 2082print_message_lines(Stream, Prefix, Lines) :-
 2083    insert_prefix(Lines, Prefix, _, PrefixLines),
 2084    print_message_lines(Stream, PrefixLines).
 insert_prefix(+Lines, +Prefix, +Ctx, -PrefixedLines)
 2088insert_prefix([at_same_line|Lines0], Prefix, Ctx, Lines) :-
 2089    !,
 2090    prefix_nl(Lines0, Prefix, Ctx, Lines).
 2091insert_prefix(Lines0, Prefix, Ctx, [prefix(Prefix)|Lines]) :-
 2092    prefix_nl(Lines0, Prefix, Ctx, Lines).
 2093
 2094prefix_nl([], _, _, [nl]).
 2095prefix_nl([nl], _, _, [nl]) :- !.
 2096prefix_nl([flush], _, _, [flush]) :- !.
 2097prefix_nl([nl|T0], Prefix, Ctx, [nl, prefix(Prefix)|T]) :-
 2098    !,
 2099    prefix_nl(T0, Prefix, Ctx, T).
 2100prefix_nl([ansi(Attrs,Fmt,Args)|T0], Prefix, Ctx,
 2101          [ansi(Attrs,Fmt,Args,Ctx)|T]) :-
 2102    !,
 2103    prefix_nl(T0, Prefix, Ctx, T).
 2104prefix_nl([H|T0], Prefix, Ctx, [H|T]) :-
 2105    prefix_nl(T0, Prefix, Ctx, T).
 print_message_lines(+Stream, +Lines)
 2109print_message_lines(Stream, Lines) :-
 2110    with_output_to(
 2111        Stream,
 2112        notrace(print_message_lines_guarded(current_output, Lines))).
 2113
 2114print_message_lines_guarded(_, []) :- !.
 2115print_message_lines_guarded(S, [H|T]) :-
 2116    line_element(S, H),
 2117    print_message_lines_guarded(S, T).
 2118
 2119line_element(S, E) :-
 2120    prolog:message_line_element(S, E),
 2121    !.
 2122line_element(S, full_stop) :-
 2123    !,
 2124    '$put_token'(S, '.').           % insert space if needed.
 2125line_element(S, nl) :-
 2126    !,
 2127    nl(S).
 2128line_element(S, prefix(Fmt-Args)) :-
 2129    !,
 2130    safe_format(S, Fmt, Args).
 2131line_element(S, prefix(Fmt)) :-
 2132    !,
 2133    safe_format(S, Fmt, []).
 2134line_element(S, flush) :-
 2135    !,
 2136    flush_output(S).
 2137line_element(S, Fmt-Args) :-
 2138    !,
 2139    safe_format(S, Fmt, Args).
 2140line_element(S, ansi(_, Fmt, Args)) :-
 2141    !,
 2142    safe_format(S, Fmt, Args).
 2143line_element(S, ansi(_, Fmt, Args, _Ctx)) :-
 2144    !,
 2145    safe_format(S, Fmt, Args).
 2146line_element(_, begin(_Level, _Ctx)) :- !.
 2147line_element(_, end(_Ctx)) :- !.
 2148line_element(S, Fmt) :-
 2149    safe_format(S, Fmt, []).
 safe_format(+Stream, +Format, +Args) is det
 2153safe_format(S, Fmt, Args) :-
 2154    E = error(_,_),
 2155    catch(format(S,Fmt,Args), E,
 2156          format_failed(S,Fmt,Args,E)).
 2157
 2158format_failed(S, _Fmt, _Args, E) :-
 2159    E = error(io_error(_,S),_),
 2160    !,
 2161    throw(E).
 2162format_failed(S, Fmt, Args, error(E,_)) :-
 2163    format(S, '~N    [[ EXCEPTION while printing message ~q~n\c
 2164                        ~7|with arguments ~W:~n\c
 2165                        ~7|raised: ~W~n~4|]]~n',
 2166           [ Fmt,
 2167             Args, [quoted(true), max_depth(10)],
 2168             E, [quoted(true), max_depth(10)]
 2169           ]).
 message_to_string(+Term, -String)
Translate an error term into a string
 2175message_to_string(Term, Str) :-
 2176    translate_message(Term, Actions, []),
 2177    !,
 2178    actions_to_format(Actions, Fmt, Args),
 2179    format(string(Str), Fmt, Args).
 2180
 2181actions_to_format([], '', []) :- !.
 2182actions_to_format([nl], '', []) :- !.
 2183actions_to_format([Term, nl], Fmt, Args) :-
 2184    !,
 2185    actions_to_format([Term], Fmt, Args).
 2186actions_to_format([nl|T], Fmt, Args) :-
 2187    !,
 2188    actions_to_format(T, Fmt0, Args),
 2189    atom_concat('~n', Fmt0, Fmt).
 2190actions_to_format([ansi(_Attrs, Fmt0, Args0)|Tail], Fmt, Args) :-
 2191    !,
 2192    actions_to_format(Tail, Fmt1, Args1),
 2193    atom_concat(Fmt0, Fmt1, Fmt),
 2194    append_args(Args0, Args1, Args).
 2195actions_to_format([Fmt0-Args0|Tail], Fmt, Args) :-
 2196    !,
 2197    actions_to_format(Tail, Fmt1, Args1),
 2198    atom_concat(Fmt0, Fmt1, Fmt),
 2199    append_args(Args0, Args1, Args).
 2200actions_to_format([Skip|T], Fmt, Args) :-
 2201    action_skip(Skip),
 2202    !,
 2203    actions_to_format(T, Fmt, Args).
 2204actions_to_format([Term|Tail], Fmt, Args) :-
 2205    atomic(Term),
 2206    !,
 2207    actions_to_format(Tail, Fmt1, Args),
 2208    atom_concat(Term, Fmt1, Fmt).
 2209actions_to_format([Term|Tail], Fmt, Args) :-
 2210    actions_to_format(Tail, Fmt1, Args1),
 2211    atom_concat('~w', Fmt1, Fmt),
 2212    append_args([Term], Args1, Args).
 2213
 2214action_skip(at_same_line).
 2215action_skip(flush).
 2216action_skip(begin(_Level, _Ctx)).
 2217action_skip(end(_Ctx)).
 2218
 2219append_args(M:Args0, Args1, M:Args) :-
 2220    !,
 2221    strip_module(Args1, _, A1),
 2222    '$append'(Args0, A1, Args).
 2223append_args(Args0, Args1, Args) :-
 2224    strip_module(Args1, _, A1),
 2225    '$append'(Args0, A1, Args).
 2226
 2227
 2228                 /*******************************
 2229                 *    MESSAGES TO PRINT ONCE    *
 2230                 *******************************/
 2231
 2232:- dynamic
 2233    printed/2.
 print_once(Message, Level)
True for messages that must be printed only once.
 2239print_once(compatibility(_), _).
 2240print_once(null_byte_in_path(_), _).
 2241print_once(deprecated(_), _).
 must_print(+Level, +Message)
True if the message must be printed.
 2247must_print(Level, Message) :-
 2248    nonvar(Message),
 2249    print_once(Message, Level),
 2250    !,
 2251    \+ printed(Message, Level),
 2252    assert(printed(Message, Level)).
 2253must_print(_, _)