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

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