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

 1611msg_context(Prefix0, Prefix) :-
 1612    current_prolog_flag(message_context, Context),
 1613    is_list(Context),
 1614    !,
 1615    add_message_context(Context, Prefix0, Prefix).
 1616msg_context(Prefix, Prefix).
 1617
 1618add_message_context([], Prefix, Prefix).
 1619add_message_context([H|T], Prefix0, Prefix) :-
 1620    (   add_message_context1(H, Prefix0, Prefix1)
 1621    ->  true
 1622    ;   Prefix1 = Prefix0
 1623    ),
 1624    add_message_context(T, Prefix1, Prefix).
 1625
 1626add_message_context1(Context, Prefix0, Prefix) :-
 1627    prolog:message_prefix_hook(Context, Extra),
 1628    atomics_to_string([Prefix0, Extra, ' '], Prefix).
 1629add_message_context1(time, Prefix0, Prefix) :-
 1630    get_time(Now),
 1631    format_time(string(S), '%T.%3f ', Now),
 1632    string_concat(Prefix0, S, Prefix).
 1633add_message_context1(time(Format), Prefix0, Prefix) :-
 1634    get_time(Now),
 1635    format_time(string(S), Format, Now),
 1636    atomics_to_string([Prefix0, S, ' '], Prefix).
 1637add_message_context1(thread, Prefix0, Prefix) :-
 1638    thread_self(Id0),
 1639    Id0 \== main,
 1640    !,
 1641    (   atom(Id0)
 1642    ->  Id = Id0
 1643    ;   thread_property(Id0, id(Id))
 1644    ),
 1645    format(string(Prefix), '~w[Thread ~w] ', [Prefix0, Id]).
 print_message_lines(+Stream, +PrefixOrKind, +Lines)
Quintus compatibility predicate to print message lines using a prefix.
 1652print_message_lines(Stream, kind(Kind), Lines) :-
 1653    !,
 1654    msg_property(Kind, prefix(Prefix)),
 1655    insert_prefix(Lines, Prefix, Ctx, PrefixLines),
 1656    '$append'([ begin(Kind, Ctx)
 1657              | PrefixLines
 1658              ],
 1659              [ end(Ctx)
 1660              ],
 1661              AllLines),
 1662    print_message_lines(Stream, AllLines).
 1663print_message_lines(Stream, Prefix, Lines) :-
 1664    insert_prefix(Lines, Prefix, _, PrefixLines),
 1665    print_message_lines(Stream, PrefixLines).
 insert_prefix(+Lines, +Prefix, +Ctx, -PrefixedLines)
 1669insert_prefix([at_same_line|Lines0], Prefix, Ctx, Lines) :-
 1670    !,
 1671    prefix_nl(Lines0, Prefix, Ctx, Lines).
 1672insert_prefix(Lines0, Prefix, Ctx, [prefix(Prefix)|Lines]) :-
 1673    prefix_nl(Lines0, Prefix, Ctx, Lines).
 1674
 1675prefix_nl([], _, _, [nl]).
 1676prefix_nl([nl], _, _, [nl]) :- !.
 1677prefix_nl([flush], _, _, [flush]) :- !.
 1678prefix_nl([nl|T0], Prefix, Ctx, [nl, prefix(Prefix)|T]) :-
 1679    !,
 1680    prefix_nl(T0, Prefix, Ctx, T).
 1681prefix_nl([ansi(Attrs,Fmt,Args)|T0], Prefix, Ctx,
 1682          [ansi(Attrs,Fmt,Args,Ctx)|T]) :-
 1683    !,
 1684    prefix_nl(T0, Prefix, Ctx, T).
 1685prefix_nl([H|T0], Prefix, Ctx, [H|T]) :-
 1686    prefix_nl(T0, Prefix, Ctx, T).
 print_message_lines(+Stream, +Lines)
 1690print_message_lines(Stream, Lines) :-
 1691    with_output_to(
 1692        Stream,
 1693        notrace(print_message_lines_guarded(current_output, Lines))).
 1694
 1695print_message_lines_guarded(_, []) :- !.
 1696print_message_lines_guarded(S, [H|T]) :-
 1697    line_element(S, H),
 1698    print_message_lines_guarded(S, T).
 1699
 1700line_element(S, E) :-
 1701    prolog:message_line_element(S, E),
 1702    !.
 1703line_element(S, full_stop) :-
 1704    !,
 1705    '$put_token'(S, '.').           % insert space if needed.
 1706line_element(S, nl) :-
 1707    !,
 1708    nl(S).
 1709line_element(S, prefix(Fmt-Args)) :-
 1710    !,
 1711    safe_format(S, Fmt, Args).
 1712line_element(S, prefix(Fmt)) :-
 1713    !,
 1714    safe_format(S, Fmt, []).
 1715line_element(S, flush) :-
 1716    !,
 1717    flush_output(S).
 1718line_element(S, Fmt-Args) :-
 1719    !,
 1720    safe_format(S, Fmt, Args).
 1721line_element(S, ansi(_, Fmt, Args)) :-
 1722    !,
 1723    safe_format(S, Fmt, Args).
 1724line_element(S, ansi(_, Fmt, Args, _Ctx)) :-
 1725    !,
 1726    safe_format(S, Fmt, Args).
 1727line_element(_, begin(_Level, _Ctx)) :- !.
 1728line_element(_, end(_Ctx)) :- !.
 1729line_element(S, Fmt) :-
 1730    safe_format(S, Fmt, []).
 safe_format(+Stream, +Format, +Args) is det
 1734safe_format(S, Fmt, Args) :-
 1735    E = error(_,_),
 1736    catch(format(S,Fmt,Args), E,
 1737          format_failed(S,Fmt,Args,E)).
 1738
 1739format_failed(S, _Fmt, _Args, E) :-
 1740    E = error(io_error(_,S),_),
 1741    !,
 1742    throw(E).
 1743format_failed(S, Fmt, Args, error(E,_)) :-
 1744    format(S, '~N    [[ EXCEPTION while printing message ~q~n\c
 1745                        ~7|with arguments ~W:~n\c
 1746                        ~7|raised: ~W~n~4|]]~n',
 1747           [ Fmt,
 1748             Args, [quoted(true), max_depth(10)],
 1749             E, [quoted(true), max_depth(10)]
 1750           ]).
 message_to_string(+Term, -String)
Translate an error term into a string
 1756message_to_string(Term, Str) :-
 1757    translate_message(Term, Actions, []),
 1758    !,
 1759    actions_to_format(Actions, Fmt, Args),
 1760    format(string(Str), Fmt, Args).
 1761
 1762actions_to_format([], '', []) :- !.
 1763actions_to_format([nl], '', []) :- !.
 1764actions_to_format([Term, nl], Fmt, Args) :-
 1765    !,
 1766    actions_to_format([Term], Fmt, Args).
 1767actions_to_format([nl|T], Fmt, Args) :-
 1768    !,
 1769    actions_to_format(T, Fmt0, Args),
 1770    atom_concat('~n', Fmt0, Fmt).
 1771actions_to_format([Skip|T], Fmt, Args) :-
 1772    action_skip(Skip),
 1773    !,
 1774    actions_to_format(T, Fmt, Args).
 1775actions_to_format([Fmt0-Args0|Tail], Fmt, Args) :-
 1776    !,
 1777    actions_to_format(Tail, Fmt1, Args1),
 1778    atom_concat(Fmt0, Fmt1, Fmt),
 1779    append_args(Args0, Args1, Args).
 1780actions_to_format([Term|Tail], Fmt, Args) :-
 1781    atomic(Term),
 1782    !,
 1783    actions_to_format(Tail, Fmt1, Args),
 1784    atom_concat(Term, Fmt1, Fmt).
 1785actions_to_format([Term|Tail], Fmt, Args) :-
 1786    actions_to_format(Tail, Fmt1, Args1),
 1787    atom_concat('~w', Fmt1, Fmt),
 1788    append_args([Term], Args1, Args).
 1789
 1790action_skip(at_same_line).
 1791action_skip(flush).
 1792action_skip(ansi(_Attrs, _Fmt, _Args)).
 1793action_skip(begin(_Level, _Ctx)).
 1794action_skip(end(_Ctx)).
 1795
 1796append_args(M:Args0, Args1, M:Args) :-
 1797    !,
 1798    strip_module(Args1, _, A1),
 1799    '$append'(Args0, A1, Args).
 1800append_args(Args0, Args1, Args) :-
 1801    strip_module(Args1, _, A1),
 1802    '$append'(Args0, A1, Args).
 1803
 1804
 1805                 /*******************************
 1806                 *    MESSAGES TO PRINT ONCE    *
 1807                 *******************************/
 1808
 1809:- dynamic
 1810    printed/2.
 print_once(Message, Level)
True for messages that must be printed only once.
 1816print_once(compatibility(_), _).
 1817print_once(null_byte_in_path(_), _).
 1818print_once(deprecated(_), _).
 must_print(+Level, +Message)
True if the message must be printed.
 1824must_print(Level, Message) :-
 1825    nonvar(Message),
 1826    print_once(Message, Level),
 1827    !,
 1828    \+ printed(Message, Level),
 1829    assert(printed(Message, Level)).
 1830must_print(_, _)