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

 2255msg_context(Prefix0, Prefix) :-
 2256    current_prolog_flag(message_context, Context),
 2257    is_list(Context),
 2258    !,
 2259    add_message_context(Context, Prefix0, Prefix).
 2260msg_context(Prefix, Prefix).
 2261
 2262add_message_context([], Prefix, Prefix).
 2263add_message_context([H|T], Prefix0, Prefix) :-
 2264    (   add_message_context1(H, Prefix0, Prefix1)
 2265    ->  true
 2266    ;   Prefix1 = Prefix0
 2267    ),
 2268    add_message_context(T, Prefix1, Prefix).
 2269
 2270add_message_context1(Context, Prefix0, Prefix) :-
 2271    prolog:message_prefix_hook(Context, Extra),
 2272    atomics_to_string([Prefix0, Extra, ' '], Prefix).
 2273add_message_context1(time, Prefix0, Prefix) :-
 2274    get_time(Now),
 2275    format_time(string(S), '%T.%3f ', Now),
 2276    string_concat(Prefix0, S, Prefix).
 2277add_message_context1(time(Format), Prefix0, Prefix) :-
 2278    get_time(Now),
 2279    format_time(string(S), Format, Now),
 2280    atomics_to_string([Prefix0, S, ' '], Prefix).
 2281add_message_context1(thread, Prefix0, Prefix) :-
 2282    \+ current_prolog_flag(toplevel_thread, true),
 2283    thread_self(Id0),
 2284    !,
 2285    (   atom(Id0)
 2286    ->  Id = Id0
 2287    ;   thread_property(Id0, id(Id))
 2288    ),
 2289    format(string(Prefix), '~w[Thread ~w] ', [Prefix0, Id]).
 print_message_lines(+Stream, +PrefixOrKind, +Lines)
Quintus compatibility predicate to print message lines using a prefix.
 2296print_message_lines(Stream, kind(Kind), Lines) :-
 2297    !,
 2298    msg_property(Kind, prefix(Prefix)),
 2299    insert_prefix(Lines, Prefix, Ctx, PrefixLines),
 2300    '$append'([ begin(Kind, Ctx)
 2301              | PrefixLines
 2302              ],
 2303              [ end(Ctx)
 2304              ],
 2305              AllLines),
 2306    print_message_lines(Stream, AllLines).
 2307print_message_lines(Stream, Prefix, Lines) :-
 2308    insert_prefix(Lines, Prefix, _, PrefixLines),
 2309    print_message_lines(Stream, PrefixLines).
 insert_prefix(+Lines, +Prefix, +Ctx, -PrefixedLines)
 2313insert_prefix([at_same_line|Lines0], Prefix, Ctx, Lines) :-
 2314    !,
 2315    prefix_nl(Lines0, Prefix, Ctx, Lines).
 2316insert_prefix(Lines0, Prefix, Ctx, [prefix(Prefix)|Lines]) :-
 2317    prefix_nl(Lines0, Prefix, Ctx, Lines).
 2318
 2319prefix_nl([], _, _, [nl]).
 2320prefix_nl([nl], _, _, [nl]) :- !.
 2321prefix_nl([flush], _, _, [flush]) :- !.
 2322prefix_nl([nl|T0], Prefix, Ctx, [nl, prefix(Prefix)|T]) :-
 2323    !,
 2324    prefix_nl(T0, Prefix, Ctx, T).
 2325prefix_nl([ansi(Attrs,Fmt,Args)|T0], Prefix, Ctx,
 2326          [ansi(Attrs,Fmt,Args,Ctx)|T]) :-
 2327    !,
 2328    prefix_nl(T0, Prefix, Ctx, T).
 2329prefix_nl([H|T0], Prefix, Ctx, [H|T]) :-
 2330    prefix_nl(T0, Prefix, Ctx, T).
 print_message_lines(+Stream, +Lines)
 2334print_message_lines(Stream, Lines) :-
 2335    with_output_to(
 2336        Stream,
 2337        notrace(print_message_lines_guarded(current_output, Lines))).
 2338
 2339print_message_lines_guarded(_, []) :- !.
 2340print_message_lines_guarded(S, [H|T]) :-
 2341    line_element(S, H),
 2342    print_message_lines_guarded(S, T).
 2343
 2344line_element(S, E) :-
 2345    prolog:message_line_element(S, E),
 2346    !.
 2347line_element(S, full_stop) :-
 2348    !,
 2349    '$put_token'(S, '.').           % insert space if needed.
 2350line_element(S, nl) :-
 2351    !,
 2352    nl(S).
 2353line_element(S, prefix(Fmt-Args)) :-
 2354    !,
 2355    safe_format(S, Fmt, Args).
 2356line_element(S, prefix(Fmt)) :-
 2357    !,
 2358    safe_format(S, Fmt, []).
 2359line_element(S, flush) :-
 2360    !,
 2361    flush_output(S).
 2362line_element(S, Fmt-Args) :-
 2363    !,
 2364    safe_format(S, Fmt, Args).
 2365line_element(S, ansi(_, Fmt, Args)) :-
 2366    !,
 2367    safe_format(S, Fmt, Args).
 2368line_element(S, ansi(_, Fmt, Args, _Ctx)) :-
 2369    !,
 2370    safe_format(S, Fmt, Args).
 2371line_element(S, url(URL)) :-
 2372    !,
 2373    print_link(S, URL).
 2374line_element(S, url(_URL, Fmt-Args)) :-
 2375    !,
 2376    safe_format(S, Fmt, Args).
 2377line_element(S, url(_URL, Fmt)) :-
 2378    !,
 2379    safe_format(S, Fmt, []).
 2380line_element(_, begin(_Level, _Ctx)) :- !.
 2381line_element(_, end(_Ctx)) :- !.
 2382line_element(S, Fmt) :-
 2383    safe_format(S, Fmt, []).
 2384
 2385print_link(S, File:Line:Column) :-
 2386    !,
 2387    safe_format(S, '~w:~d:~d', [File, Line, Column]).
 2388print_link(S, File:Line) :-
 2389    !,
 2390    safe_format(S, '~w:~d', [File, Line]).
 2391print_link(S, File) :-
 2392    safe_format(S, '~w', [File]).
 safe_format(+Stream, +Format, +Args) is det
 2396safe_format(S, Fmt, Args) :-
 2397    E = error(_,_),
 2398    catch(format(S,Fmt,Args), E,
 2399          format_failed(S,Fmt,Args,E)).
 2400
 2401format_failed(S, _Fmt, _Args, E) :-
 2402    stream_property(S, error(true)),
 2403    !,
 2404    throw(E).
 2405format_failed(S, Fmt, Args, error(E,_)) :-
 2406    format(S, '~N    [[ EXCEPTION while printing message ~q~n\c
 2407                        ~7|with arguments ~W:~n\c
 2408                        ~7|raised: ~W~n~4|]]~n',
 2409           [ Fmt,
 2410             Args, [quoted(true), max_depth(10)],
 2411             E, [quoted(true), max_depth(10)]
 2412           ]).
 message_to_string(+Term, -String)
Translate an error term into a string
 2418message_to_string(Term, Str) :-
 2419    translate_message(Term, Actions, []),
 2420    !,
 2421    actions_to_format(Actions, Fmt, Args),
 2422    format(string(Str), Fmt, Args).
 2423
 2424actions_to_format([], '', []) :- !.
 2425actions_to_format([nl], '', []) :- !.
 2426actions_to_format([Term, nl], Fmt, Args) :-
 2427    !,
 2428    actions_to_format([Term], Fmt, Args).
 2429actions_to_format([nl|T], Fmt, Args) :-
 2430    !,
 2431    actions_to_format(T, Fmt0, Args),
 2432    atom_concat('~n', Fmt0, Fmt).
 2433actions_to_format([ansi(_Attrs, Fmt0, Args0)|Tail], Fmt, Args) :-
 2434    !,
 2435    actions_to_format(Tail, Fmt1, Args1),
 2436    atom_concat(Fmt0, Fmt1, Fmt),
 2437    append_args(Args0, Args1, Args).
 2438actions_to_format([url(Pos)|Tail], Fmt, Args) :-
 2439    !,
 2440    actions_to_format(Tail, Fmt1, Args1),
 2441    url_actions_to_format(url(Pos), Fmt1, Args1, Fmt, Args).
 2442actions_to_format([url(URL, Label)|Tail], Fmt, Args) :-
 2443    !,
 2444    actions_to_format(Tail, Fmt1, Args1),
 2445    url_actions_to_format(url(URL, Label), Fmt1, Args1, Fmt, Args).
 2446actions_to_format([Fmt0-Args0|Tail], Fmt, Args) :-
 2447    !,
 2448    actions_to_format(Tail, Fmt1, Args1),
 2449    atom_concat(Fmt0, Fmt1, Fmt),
 2450    append_args(Args0, Args1, Args).
 2451actions_to_format([Skip|T], Fmt, Args) :-
 2452    action_skip(Skip),
 2453    !,
 2454    actions_to_format(T, Fmt, Args).
 2455actions_to_format([Term|Tail], Fmt, Args) :-
 2456    atomic(Term),
 2457    !,
 2458    actions_to_format(Tail, Fmt1, Args),
 2459    atom_concat(Term, Fmt1, Fmt).
 2460actions_to_format([Term|Tail], Fmt, Args) :-
 2461    actions_to_format(Tail, Fmt1, Args1),
 2462    atom_concat('~w', Fmt1, Fmt),
 2463    append_args([Term], Args1, Args).
 2464
 2465action_skip(at_same_line).
 2466action_skip(flush).
 2467action_skip(begin(_Level, _Ctx)).
 2468action_skip(end(_Ctx)).
 2469
 2470url_actions_to_format(url(File:Line:Column), Fmt1, Args1, Fmt, Args) :-
 2471    !,
 2472    atom_concat('~w:~d:~d', Fmt1, Fmt),
 2473    append_args([File,Line,Column], Args1, Args).
 2474url_actions_to_format(url(File:Line), Fmt1, Args1, Fmt, Args) :-
 2475    !,
 2476    atom_concat('~w:~d', Fmt1, Fmt),
 2477    append_args([File,Line], Args1, Args).
 2478url_actions_to_format(url(File), Fmt1, Args1, Fmt, Args) :-
 2479    !,
 2480    atom_concat('~w', Fmt1, Fmt),
 2481    append_args([File], Args1, Args).
 2482url_actions_to_format(url(_URL, Label), Fmt1, Args1, Fmt, Args) :-
 2483    !,
 2484    atom_concat('~w', Fmt1, Fmt),
 2485    append_args([Label], Args1, Args).
 2486
 2487
 2488append_args(M:Args0, Args1, M:Args) :-
 2489    !,
 2490    strip_module(Args1, _, A1),
 2491    to_list(Args0, Args01),
 2492    '$append'(Args01, A1, Args).
 2493append_args(Args0, Args1, Args) :-
 2494    strip_module(Args1, _, A1),
 2495    to_list(Args0, Args01),
 2496    '$append'(Args01, A1, Args).
 2497
 2498                 /*******************************
 2499                 *    MESSAGES TO PRINT ONCE    *
 2500                 *******************************/
 2501
 2502:- dynamic
 2503    printed/2.
 print_once(Message, Level)
True for messages that must be printed only once.
 2509print_once(compatibility(_), _).
 2510print_once(null_byte_in_path(_), _).
 2511print_once(deprecated(_), _).
 must_print(+Level, +Message)
True if the message must be printed.
 2517must_print(Level, Message) :-
 2518    nonvar(Message),
 2519    print_once(Message, Level),
 2520    !,
 2521    \+ printed(Message, Level),
 2522    assert(printed(Message, Level)).
 2523must_print(_, _)