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

 1647msg_context(Prefix0, Prefix) :-
 1648    current_prolog_flag(message_context, Context),
 1649    is_list(Context),
 1650    !,
 1651    add_message_context(Context, Prefix0, Prefix).
 1652msg_context(Prefix, Prefix).
 1653
 1654add_message_context([], Prefix, Prefix).
 1655add_message_context([H|T], Prefix0, Prefix) :-
 1656    (   add_message_context1(H, Prefix0, Prefix1)
 1657    ->  true
 1658    ;   Prefix1 = Prefix0
 1659    ),
 1660    add_message_context(T, Prefix1, Prefix).
 1661
 1662add_message_context1(Context, Prefix0, Prefix) :-
 1663    prolog:message_prefix_hook(Context, Extra),
 1664    atomics_to_string([Prefix0, Extra, ' '], Prefix).
 1665add_message_context1(time, Prefix0, Prefix) :-
 1666    get_time(Now),
 1667    format_time(string(S), '%T.%3f ', Now),
 1668    string_concat(Prefix0, S, Prefix).
 1669add_message_context1(time(Format), Prefix0, Prefix) :-
 1670    get_time(Now),
 1671    format_time(string(S), Format, Now),
 1672    atomics_to_string([Prefix0, S, ' '], Prefix).
 1673add_message_context1(thread, Prefix0, Prefix) :-
 1674    thread_self(Id0),
 1675    Id0 \== main,
 1676    !,
 1677    (   atom(Id0)
 1678    ->  Id = Id0
 1679    ;   thread_property(Id0, id(Id))
 1680    ),
 1681    format(string(Prefix), '~w[Thread ~w] ', [Prefix0, Id]).
 print_message_lines(+Stream, +PrefixOrKind, +Lines)
Quintus compatibility predicate to print message lines using a prefix.
 1688print_message_lines(Stream, kind(Kind), Lines) :-
 1689    !,
 1690    msg_property(Kind, prefix(Prefix)),
 1691    insert_prefix(Lines, Prefix, Ctx, PrefixLines),
 1692    '$append'([ begin(Kind, Ctx)
 1693              | PrefixLines
 1694              ],
 1695              [ end(Ctx)
 1696              ],
 1697              AllLines),
 1698    print_message_lines(Stream, AllLines).
 1699print_message_lines(Stream, Prefix, Lines) :-
 1700    insert_prefix(Lines, Prefix, _, PrefixLines),
 1701    print_message_lines(Stream, PrefixLines).
 insert_prefix(+Lines, +Prefix, +Ctx, -PrefixedLines)
 1705insert_prefix([at_same_line|Lines0], Prefix, Ctx, Lines) :-
 1706    !,
 1707    prefix_nl(Lines0, Prefix, Ctx, Lines).
 1708insert_prefix(Lines0, Prefix, Ctx, [prefix(Prefix)|Lines]) :-
 1709    prefix_nl(Lines0, Prefix, Ctx, Lines).
 1710
 1711prefix_nl([], _, _, [nl]).
 1712prefix_nl([nl], _, _, [nl]) :- !.
 1713prefix_nl([flush], _, _, [flush]) :- !.
 1714prefix_nl([nl|T0], Prefix, Ctx, [nl, prefix(Prefix)|T]) :-
 1715    !,
 1716    prefix_nl(T0, Prefix, Ctx, T).
 1717prefix_nl([ansi(Attrs,Fmt,Args)|T0], Prefix, Ctx,
 1718          [ansi(Attrs,Fmt,Args,Ctx)|T]) :-
 1719    !,
 1720    prefix_nl(T0, Prefix, Ctx, T).
 1721prefix_nl([H|T0], Prefix, Ctx, [H|T]) :-
 1722    prefix_nl(T0, Prefix, Ctx, T).
 print_message_lines(+Stream, +Lines)
 1726print_message_lines(Stream, Lines) :-
 1727    with_output_to(
 1728        Stream,
 1729        notrace(print_message_lines_guarded(current_output, Lines))).
 1730
 1731print_message_lines_guarded(_, []) :- !.
 1732print_message_lines_guarded(S, [H|T]) :-
 1733    line_element(S, H),
 1734    print_message_lines_guarded(S, T).
 1735
 1736line_element(S, E) :-
 1737    prolog:message_line_element(S, E),
 1738    !.
 1739line_element(S, full_stop) :-
 1740    !,
 1741    '$put_token'(S, '.').           % insert space if needed.
 1742line_element(S, nl) :-
 1743    !,
 1744    nl(S).
 1745line_element(S, prefix(Fmt-Args)) :-
 1746    !,
 1747    safe_format(S, Fmt, Args).
 1748line_element(S, prefix(Fmt)) :-
 1749    !,
 1750    safe_format(S, Fmt, []).
 1751line_element(S, flush) :-
 1752    !,
 1753    flush_output(S).
 1754line_element(S, Fmt-Args) :-
 1755    !,
 1756    safe_format(S, Fmt, Args).
 1757line_element(S, ansi(_, Fmt, Args)) :-
 1758    !,
 1759    safe_format(S, Fmt, Args).
 1760line_element(S, ansi(_, Fmt, Args, _Ctx)) :-
 1761    !,
 1762    safe_format(S, Fmt, Args).
 1763line_element(_, begin(_Level, _Ctx)) :- !.
 1764line_element(_, end(_Ctx)) :- !.
 1765line_element(S, Fmt) :-
 1766    safe_format(S, Fmt, []).
 safe_format(+Stream, +Format, +Args) is det
 1770safe_format(S, Fmt, Args) :-
 1771    E = error(_,_),
 1772    catch(format(S,Fmt,Args), E,
 1773          format_failed(S,Fmt,Args,E)).
 1774
 1775format_failed(S, _Fmt, _Args, E) :-
 1776    E = error(io_error(_,S),_),
 1777    !,
 1778    throw(E).
 1779format_failed(S, Fmt, Args, error(E,_)) :-
 1780    format(S, '~N    [[ EXCEPTION while printing message ~q~n\c
 1781                        ~7|with arguments ~W:~n\c
 1782                        ~7|raised: ~W~n~4|]]~n',
 1783           [ Fmt,
 1784             Args, [quoted(true), max_depth(10)],
 1785             E, [quoted(true), max_depth(10)]
 1786           ]).
 message_to_string(+Term, -String)
Translate an error term into a string
 1792message_to_string(Term, Str) :-
 1793    translate_message(Term, Actions, []),
 1794    !,
 1795    actions_to_format(Actions, Fmt, Args),
 1796    format(string(Str), Fmt, Args).
 1797
 1798actions_to_format([], '', []) :- !.
 1799actions_to_format([nl], '', []) :- !.
 1800actions_to_format([Term, nl], Fmt, Args) :-
 1801    !,
 1802    actions_to_format([Term], Fmt, Args).
 1803actions_to_format([nl|T], Fmt, Args) :-
 1804    !,
 1805    actions_to_format(T, Fmt0, Args),
 1806    atom_concat('~n', Fmt0, Fmt).
 1807actions_to_format([Skip|T], Fmt, Args) :-
 1808    action_skip(Skip),
 1809    !,
 1810    actions_to_format(T, Fmt, Args).
 1811actions_to_format([Fmt0-Args0|Tail], Fmt, Args) :-
 1812    !,
 1813    actions_to_format(Tail, Fmt1, Args1),
 1814    atom_concat(Fmt0, Fmt1, Fmt),
 1815    append_args(Args0, Args1, Args).
 1816actions_to_format([Term|Tail], Fmt, Args) :-
 1817    atomic(Term),
 1818    !,
 1819    actions_to_format(Tail, Fmt1, Args),
 1820    atom_concat(Term, Fmt1, Fmt).
 1821actions_to_format([Term|Tail], Fmt, Args) :-
 1822    actions_to_format(Tail, Fmt1, Args1),
 1823    atom_concat('~w', Fmt1, Fmt),
 1824    append_args([Term], Args1, Args).
 1825
 1826action_skip(at_same_line).
 1827action_skip(flush).
 1828action_skip(ansi(_Attrs, _Fmt, _Args)).
 1829action_skip(begin(_Level, _Ctx)).
 1830action_skip(end(_Ctx)).
 1831
 1832append_args(M:Args0, Args1, M:Args) :-
 1833    !,
 1834    strip_module(Args1, _, A1),
 1835    '$append'(Args0, A1, Args).
 1836append_args(Args0, Args1, Args) :-
 1837    strip_module(Args1, _, A1),
 1838    '$append'(Args0, A1, Args).
 1839
 1840
 1841                 /*******************************
 1842                 *    MESSAGES TO PRINT ONCE    *
 1843                 *******************************/
 1844
 1845:- dynamic
 1846    printed/2.
 print_once(Message, Level)
True for messages that must be printed only once.
 1852print_once(compatibility(_), _).
 1853print_once(null_byte_in_path(_), _).
 1854print_once(deprecated(_), _).
 must_print(+Level, +Message)
True if the message must be printed.
 1860must_print(Level, Message) :-
 1861    nonvar(Message),
 1862    print_once(Message, Level),
 1863    !,
 1864    \+ printed(Message, Level),
 1865    assert(printed(Message, Level)).
 1866must_print(_, _)