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

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