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

 1695msg_context(Prefix0, Prefix) :-
 1696    current_prolog_flag(message_context, Context),
 1697    is_list(Context),
 1698    !,
 1699    add_message_context(Context, Prefix0, Prefix).
 1700msg_context(Prefix, Prefix).
 1701
 1702add_message_context([], Prefix, Prefix).
 1703add_message_context([H|T], Prefix0, Prefix) :-
 1704    (   add_message_context1(H, Prefix0, Prefix1)
 1705    ->  true
 1706    ;   Prefix1 = Prefix0
 1707    ),
 1708    add_message_context(T, Prefix1, Prefix).
 1709
 1710add_message_context1(Context, Prefix0, Prefix) :-
 1711    prolog:message_prefix_hook(Context, Extra),
 1712    atomics_to_string([Prefix0, Extra, ' '], Prefix).
 1713add_message_context1(time, Prefix0, Prefix) :-
 1714    get_time(Now),
 1715    format_time(string(S), '%T.%3f ', Now),
 1716    string_concat(Prefix0, S, Prefix).
 1717add_message_context1(time(Format), Prefix0, Prefix) :-
 1718    get_time(Now),
 1719    format_time(string(S), Format, Now),
 1720    atomics_to_string([Prefix0, S, ' '], Prefix).
 1721add_message_context1(thread, Prefix0, Prefix) :-
 1722    thread_self(Id0),
 1723    Id0 \== main,
 1724    !,
 1725    (   atom(Id0)
 1726    ->  Id = Id0
 1727    ;   thread_property(Id0, id(Id))
 1728    ),
 1729    format(string(Prefix), '~w[Thread ~w] ', [Prefix0, Id]).
 print_message_lines(+Stream, +PrefixOrKind, +Lines)
Quintus compatibility predicate to print message lines using a prefix.
 1736print_message_lines(Stream, kind(Kind), Lines) :-
 1737    !,
 1738    msg_property(Kind, prefix(Prefix)),
 1739    insert_prefix(Lines, Prefix, Ctx, PrefixLines),
 1740    '$append'([ begin(Kind, Ctx)
 1741              | PrefixLines
 1742              ],
 1743              [ end(Ctx)
 1744              ],
 1745              AllLines),
 1746    print_message_lines(Stream, AllLines).
 1747print_message_lines(Stream, Prefix, Lines) :-
 1748    insert_prefix(Lines, Prefix, _, PrefixLines),
 1749    print_message_lines(Stream, PrefixLines).
 insert_prefix(+Lines, +Prefix, +Ctx, -PrefixedLines)
 1753insert_prefix([at_same_line|Lines0], Prefix, Ctx, Lines) :-
 1754    !,
 1755    prefix_nl(Lines0, Prefix, Ctx, Lines).
 1756insert_prefix(Lines0, Prefix, Ctx, [prefix(Prefix)|Lines]) :-
 1757    prefix_nl(Lines0, Prefix, Ctx, Lines).
 1758
 1759prefix_nl([], _, _, [nl]).
 1760prefix_nl([nl], _, _, [nl]) :- !.
 1761prefix_nl([flush], _, _, [flush]) :- !.
 1762prefix_nl([nl|T0], Prefix, Ctx, [nl, prefix(Prefix)|T]) :-
 1763    !,
 1764    prefix_nl(T0, Prefix, Ctx, T).
 1765prefix_nl([ansi(Attrs,Fmt,Args)|T0], Prefix, Ctx,
 1766          [ansi(Attrs,Fmt,Args,Ctx)|T]) :-
 1767    !,
 1768    prefix_nl(T0, Prefix, Ctx, T).
 1769prefix_nl([H|T0], Prefix, Ctx, [H|T]) :-
 1770    prefix_nl(T0, Prefix, Ctx, T).
 print_message_lines(+Stream, +Lines)
 1774print_message_lines(Stream, Lines) :-
 1775    with_output_to(
 1776        Stream,
 1777        notrace(print_message_lines_guarded(current_output, Lines))).
 1778
 1779print_message_lines_guarded(_, []) :- !.
 1780print_message_lines_guarded(S, [H|T]) :-
 1781    line_element(S, H),
 1782    print_message_lines_guarded(S, T).
 1783
 1784line_element(S, E) :-
 1785    prolog:message_line_element(S, E),
 1786    !.
 1787line_element(S, full_stop) :-
 1788    !,
 1789    '$put_token'(S, '.').           % insert space if needed.
 1790line_element(S, nl) :-
 1791    !,
 1792    nl(S).
 1793line_element(S, prefix(Fmt-Args)) :-
 1794    !,
 1795    safe_format(S, Fmt, Args).
 1796line_element(S, prefix(Fmt)) :-
 1797    !,
 1798    safe_format(S, Fmt, []).
 1799line_element(S, flush) :-
 1800    !,
 1801    flush_output(S).
 1802line_element(S, Fmt-Args) :-
 1803    !,
 1804    safe_format(S, Fmt, Args).
 1805line_element(S, ansi(_, Fmt, Args)) :-
 1806    !,
 1807    safe_format(S, Fmt, Args).
 1808line_element(S, ansi(_, Fmt, Args, _Ctx)) :-
 1809    !,
 1810    safe_format(S, Fmt, Args).
 1811line_element(_, begin(_Level, _Ctx)) :- !.
 1812line_element(_, end(_Ctx)) :- !.
 1813line_element(S, Fmt) :-
 1814    safe_format(S, Fmt, []).
 safe_format(+Stream, +Format, +Args) is det
 1818safe_format(S, Fmt, Args) :-
 1819    E = error(_,_),
 1820    catch(format(S,Fmt,Args), E,
 1821          format_failed(S,Fmt,Args,E)).
 1822
 1823format_failed(S, _Fmt, _Args, E) :-
 1824    E = error(io_error(_,S),_),
 1825    !,
 1826    throw(E).
 1827format_failed(S, Fmt, Args, error(E,_)) :-
 1828    format(S, '~N    [[ EXCEPTION while printing message ~q~n\c
 1829                        ~7|with arguments ~W:~n\c
 1830                        ~7|raised: ~W~n~4|]]~n',
 1831           [ Fmt,
 1832             Args, [quoted(true), max_depth(10)],
 1833             E, [quoted(true), max_depth(10)]
 1834           ]).
 message_to_string(+Term, -String)
Translate an error term into a string
 1840message_to_string(Term, Str) :-
 1841    translate_message(Term, Actions, []),
 1842    !,
 1843    actions_to_format(Actions, Fmt, Args),
 1844    format(string(Str), Fmt, Args).
 1845
 1846actions_to_format([], '', []) :- !.
 1847actions_to_format([nl], '', []) :- !.
 1848actions_to_format([Term, nl], Fmt, Args) :-
 1849    !,
 1850    actions_to_format([Term], Fmt, Args).
 1851actions_to_format([nl|T], Fmt, Args) :-
 1852    !,
 1853    actions_to_format(T, Fmt0, Args),
 1854    atom_concat('~n', Fmt0, Fmt).
 1855actions_to_format([Skip|T], Fmt, Args) :-
 1856    action_skip(Skip),
 1857    !,
 1858    actions_to_format(T, Fmt, Args).
 1859actions_to_format([Fmt0-Args0|Tail], Fmt, Args) :-
 1860    !,
 1861    actions_to_format(Tail, Fmt1, Args1),
 1862    atom_concat(Fmt0, Fmt1, Fmt),
 1863    append_args(Args0, Args1, Args).
 1864actions_to_format([Term|Tail], Fmt, Args) :-
 1865    atomic(Term),
 1866    !,
 1867    actions_to_format(Tail, Fmt1, Args),
 1868    atom_concat(Term, Fmt1, Fmt).
 1869actions_to_format([Term|Tail], Fmt, Args) :-
 1870    actions_to_format(Tail, Fmt1, Args1),
 1871    atom_concat('~w', Fmt1, Fmt),
 1872    append_args([Term], Args1, Args).
 1873
 1874action_skip(at_same_line).
 1875action_skip(flush).
 1876action_skip(ansi(_Attrs, _Fmt, _Args)).
 1877action_skip(begin(_Level, _Ctx)).
 1878action_skip(end(_Ctx)).
 1879
 1880append_args(M:Args0, Args1, M:Args) :-
 1881    !,
 1882    strip_module(Args1, _, A1),
 1883    '$append'(Args0, A1, Args).
 1884append_args(Args0, Args1, Args) :-
 1885    strip_module(Args1, _, A1),
 1886    '$append'(Args0, A1, Args).
 1887
 1888
 1889                 /*******************************
 1890                 *    MESSAGES TO PRINT ONCE    *
 1891                 *******************************/
 1892
 1893:- dynamic
 1894    printed/2.
 print_once(Message, Level)
True for messages that must be printed only once.
 1900print_once(compatibility(_), _).
 1901print_once(null_byte_in_path(_), _).
 1902print_once(deprecated(_), _).
 must_print(+Level, +Message)
True if the message must be printed.
 1908must_print(Level, Message) :-
 1909    nonvar(Message),
 1910    print_once(Message, Level),
 1911    !,
 1912    \+ printed(Message, Level),
 1913    assert(printed(Message, Level)).
 1914must_print(_, _)