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

 1784msg_context(Prefix0, Prefix) :-
 1785    current_prolog_flag(message_context, Context),
 1786    is_list(Context),
 1787    !,
 1788    add_message_context(Context, Prefix0, Prefix).
 1789msg_context(Prefix, Prefix).
 1790
 1791add_message_context([], Prefix, Prefix).
 1792add_message_context([H|T], Prefix0, Prefix) :-
 1793    (   add_message_context1(H, Prefix0, Prefix1)
 1794    ->  true
 1795    ;   Prefix1 = Prefix0
 1796    ),
 1797    add_message_context(T, Prefix1, Prefix).
 1798
 1799add_message_context1(Context, Prefix0, Prefix) :-
 1800    prolog:message_prefix_hook(Context, Extra),
 1801    atomics_to_string([Prefix0, Extra, ' '], Prefix).
 1802add_message_context1(time, Prefix0, Prefix) :-
 1803    get_time(Now),
 1804    format_time(string(S), '%T.%3f ', Now),
 1805    string_concat(Prefix0, S, Prefix).
 1806add_message_context1(time(Format), Prefix0, Prefix) :-
 1807    get_time(Now),
 1808    format_time(string(S), Format, Now),
 1809    atomics_to_string([Prefix0, S, ' '], Prefix).
 1810add_message_context1(thread, Prefix0, Prefix) :-
 1811    thread_self(Id0),
 1812    Id0 \== main,
 1813    !,
 1814    (   atom(Id0)
 1815    ->  Id = Id0
 1816    ;   thread_property(Id0, id(Id))
 1817    ),
 1818    format(string(Prefix), '~w[Thread ~w] ', [Prefix0, Id]).
 print_message_lines(+Stream, +PrefixOrKind, +Lines)
Quintus compatibility predicate to print message lines using a prefix.
 1825print_message_lines(Stream, kind(Kind), Lines) :-
 1826    !,
 1827    msg_property(Kind, prefix(Prefix)),
 1828    insert_prefix(Lines, Prefix, Ctx, PrefixLines),
 1829    '$append'([ begin(Kind, Ctx)
 1830              | PrefixLines
 1831              ],
 1832              [ end(Ctx)
 1833              ],
 1834              AllLines),
 1835    print_message_lines(Stream, AllLines).
 1836print_message_lines(Stream, Prefix, Lines) :-
 1837    insert_prefix(Lines, Prefix, _, PrefixLines),
 1838    print_message_lines(Stream, PrefixLines).
 insert_prefix(+Lines, +Prefix, +Ctx, -PrefixedLines)
 1842insert_prefix([at_same_line|Lines0], Prefix, Ctx, Lines) :-
 1843    !,
 1844    prefix_nl(Lines0, Prefix, Ctx, Lines).
 1845insert_prefix(Lines0, Prefix, Ctx, [prefix(Prefix)|Lines]) :-
 1846    prefix_nl(Lines0, Prefix, Ctx, Lines).
 1847
 1848prefix_nl([], _, _, [nl]).
 1849prefix_nl([nl], _, _, [nl]) :- !.
 1850prefix_nl([flush], _, _, [flush]) :- !.
 1851prefix_nl([nl|T0], Prefix, Ctx, [nl, prefix(Prefix)|T]) :-
 1852    !,
 1853    prefix_nl(T0, Prefix, Ctx, T).
 1854prefix_nl([ansi(Attrs,Fmt,Args)|T0], Prefix, Ctx,
 1855          [ansi(Attrs,Fmt,Args,Ctx)|T]) :-
 1856    !,
 1857    prefix_nl(T0, Prefix, Ctx, T).
 1858prefix_nl([H|T0], Prefix, Ctx, [H|T]) :-
 1859    prefix_nl(T0, Prefix, Ctx, T).
 print_message_lines(+Stream, +Lines)
 1863print_message_lines(Stream, Lines) :-
 1864    with_output_to(
 1865        Stream,
 1866        notrace(print_message_lines_guarded(current_output, Lines))).
 1867
 1868print_message_lines_guarded(_, []) :- !.
 1869print_message_lines_guarded(S, [H|T]) :-
 1870    line_element(S, H),
 1871    print_message_lines_guarded(S, T).
 1872
 1873line_element(S, E) :-
 1874    prolog:message_line_element(S, E),
 1875    !.
 1876line_element(S, full_stop) :-
 1877    !,
 1878    '$put_token'(S, '.').           % insert space if needed.
 1879line_element(S, nl) :-
 1880    !,
 1881    nl(S).
 1882line_element(S, prefix(Fmt-Args)) :-
 1883    !,
 1884    safe_format(S, Fmt, Args).
 1885line_element(S, prefix(Fmt)) :-
 1886    !,
 1887    safe_format(S, Fmt, []).
 1888line_element(S, flush) :-
 1889    !,
 1890    flush_output(S).
 1891line_element(S, Fmt-Args) :-
 1892    !,
 1893    safe_format(S, Fmt, Args).
 1894line_element(S, ansi(_, Fmt, Args)) :-
 1895    !,
 1896    safe_format(S, Fmt, Args).
 1897line_element(S, ansi(_, Fmt, Args, _Ctx)) :-
 1898    !,
 1899    safe_format(S, Fmt, Args).
 1900line_element(_, begin(_Level, _Ctx)) :- !.
 1901line_element(_, end(_Ctx)) :- !.
 1902line_element(S, Fmt) :-
 1903    safe_format(S, Fmt, []).
 safe_format(+Stream, +Format, +Args) is det
 1907safe_format(S, Fmt, Args) :-
 1908    E = error(_,_),
 1909    catch(format(S,Fmt,Args), E,
 1910          format_failed(S,Fmt,Args,E)).
 1911
 1912format_failed(S, _Fmt, _Args, E) :-
 1913    E = error(io_error(_,S),_),
 1914    !,
 1915    throw(E).
 1916format_failed(S, Fmt, Args, error(E,_)) :-
 1917    format(S, '~N    [[ EXCEPTION while printing message ~q~n\c
 1918                        ~7|with arguments ~W:~n\c
 1919                        ~7|raised: ~W~n~4|]]~n',
 1920           [ Fmt,
 1921             Args, [quoted(true), max_depth(10)],
 1922             E, [quoted(true), max_depth(10)]
 1923           ]).
 message_to_string(+Term, -String)
Translate an error term into a string
 1929message_to_string(Term, Str) :-
 1930    translate_message(Term, Actions, []),
 1931    !,
 1932    actions_to_format(Actions, Fmt, Args),
 1933    format(string(Str), Fmt, Args).
 1934
 1935actions_to_format([], '', []) :- !.
 1936actions_to_format([nl], '', []) :- !.
 1937actions_to_format([Term, nl], Fmt, Args) :-
 1938    !,
 1939    actions_to_format([Term], Fmt, Args).
 1940actions_to_format([nl|T], Fmt, Args) :-
 1941    !,
 1942    actions_to_format(T, Fmt0, Args),
 1943    atom_concat('~n', Fmt0, Fmt).
 1944actions_to_format([ansi(_Attrs, Fmt0, Args0)|Tail], Fmt, Args) :-
 1945    !,
 1946    actions_to_format(Tail, Fmt1, Args1),
 1947    atom_concat(Fmt0, Fmt1, Fmt),
 1948    append_args(Args0, Args1, Args).
 1949actions_to_format([Fmt0-Args0|Tail], Fmt, Args) :-
 1950    !,
 1951    actions_to_format(Tail, Fmt1, Args1),
 1952    atom_concat(Fmt0, Fmt1, Fmt),
 1953    append_args(Args0, Args1, Args).
 1954actions_to_format([Skip|T], Fmt, Args) :-
 1955    action_skip(Skip),
 1956    !,
 1957    actions_to_format(T, Fmt, Args).
 1958actions_to_format([Term|Tail], Fmt, Args) :-
 1959    atomic(Term),
 1960    !,
 1961    actions_to_format(Tail, Fmt1, Args),
 1962    atom_concat(Term, Fmt1, Fmt).
 1963actions_to_format([Term|Tail], Fmt, Args) :-
 1964    actions_to_format(Tail, Fmt1, Args1),
 1965    atom_concat('~w', Fmt1, Fmt),
 1966    append_args([Term], Args1, Args).
 1967
 1968action_skip(at_same_line).
 1969action_skip(flush).
 1970action_skip(begin(_Level, _Ctx)).
 1971action_skip(end(_Ctx)).
 1972
 1973append_args(M:Args0, Args1, M:Args) :-
 1974    !,
 1975    strip_module(Args1, _, A1),
 1976    '$append'(Args0, A1, Args).
 1977append_args(Args0, Args1, Args) :-
 1978    strip_module(Args1, _, A1),
 1979    '$append'(Args0, A1, Args).
 1980
 1981
 1982                 /*******************************
 1983                 *    MESSAGES TO PRINT ONCE    *
 1984                 *******************************/
 1985
 1986:- dynamic
 1987    printed/2.
 print_once(Message, Level)
True for messages that must be printed only once.
 1993print_once(compatibility(_), _).
 1994print_once(null_byte_in_path(_), _).
 1995print_once(deprecated(_), _).
 must_print(+Level, +Message)
True if the message must be printed.
 2001must_print(Level, Message) :-
 2002    nonvar(Message),
 2003    print_once(Message, Level),
 2004    !,
 2005    \+ printed(Message, Level),
 2006    assert(printed(Message, Level)).
 2007must_print(_, _)