View source with raw comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        jan@swi-prolog.org
    5    WWW:           https://www.swi-prolog.org
    6    Copyright (c)  1997-2026, University of Amsterdam
    7                              VU University Amsterdam
    8                              CWI, Amsterdam
    9                              SWI-Prolog Solutions b.v.
   10    All rights reserved.
   11
   12    Redistribution and use in source and binary forms, with or without
   13    modification, are permitted provided that the following conditions
   14    are met:
   15
   16    1. Redistributions of source code must retain the above copyright
   17       notice, this list of conditions and the following disclaimer.
   18
   19    2. Redistributions in binary form must reproduce the above copyright
   20       notice, this list of conditions and the following disclaimer in
   21       the documentation and/or other materials provided with the
   22       distribution.
   23
   24    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   25    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   26    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   27    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   28    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   29    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   30    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   31    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   32    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   34    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   35    POSSIBILITY OF SUCH DAMAGE.
   36*/
   37
   38:- module('$messages',
   39          [ print_message/2,            % +Kind, +Term
   40            print_message_lines/3,      % +Stream, +Prefix, +Lines
   41            message_to_string/2         % +Term, -String
   42          ]).   43
   44:- multifile
   45    prolog:message//1,              % entire message
   46    prolog:error_message//1,        % 1-st argument of error term
   47    prolog:message_context//1,      % Context of error messages
   48    prolog:deprecated//1,	    % Deprecated features
   49    prolog:message_location//1,     % (File) location of error messages
   50    prolog:message_line_element/2,  % Extend printing
   51    prolog:message_action/2.        % Side effects (broadcast)
   52:- dynamic
   53    prolog:message_action/2.        % Allow overruling
   54:- '$hide'((
   55    prolog:message//1,
   56    prolog:error_message//1,
   57    prolog:message_context//1,
   58    prolog:deprecated//1,
   59    prolog:message_location//1,
   60    prolog:message_line_element/2)).   61% Lang, Term versions
   62:- multifile
   63    prolog:message//2,              % entire message
   64    prolog:error_message//2,        % 1-st argument of error term
   65    prolog:message_context//2,      % Context of error messages
   66    prolog:message_location//2,	    % (File) location of error messages
   67    prolog:deprecated//2.	    % Deprecated features
   68:- '$hide'((
   69    prolog:message//2,
   70    prolog:error_message//2,
   71    prolog:message_context//2,
   72    prolog:deprecated//2,
   73    prolog:message_location//2)).   74
   75:- discontiguous
   76    prolog_message/3.   77
   78:- public
   79    translate_message//1,           % +Message (deprecated)
   80    prolog:translate_message//1.    % +Message
   81
   82:- 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)
ansi(Code, Fmt, Args)
Use ansi_format/3 for color output.
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)
deprecated
- Use code for message translation should call translate_message//1.
  106prolog:translate_message(Term) -->
  107    translate_message(Term).
 translate_message(+Term)// is det
Translate a message term into message lines. This version may be called from user and library definitions for message translation.
  114translate_message(Term) -->
  115    { nonvar(Term) },
  116    (   { message_lang(Lang) },
  117        prolog:message(Lang, Term)
  118    ;   prolog:message(Term)
  119    ),
  120    !.
  121translate_message(Term) -->
  122    { nonvar(Term) },
  123    translate_message2(Term),
  124    !.
  125translate_message(Term) -->
  126    { nonvar(Term),
  127      Term = error(_, _)
  128    },
  129    [ 'Unknown exception: ~p'-[Term] ].
  130translate_message(Term) -->
  131    [ 'Unknown message: ~p'-[Term] ].
  132
  133translate_message2(Term) -->
  134    prolog_message(Term).
  135translate_message2(error(resource_error(stack), Context)) -->
  136    !,
  137    out_of_stack(Context).
  138translate_message2(error(resource_error(tripwire(Wire, Context)), _)) -->
  139    !,
  140    tripwire_message(Wire, Context).
  141translate_message2(error(existence_error(reset, Ball), SWI)) -->
  142    swi_location(SWI),
  143    tabling_existence_error(Ball, SWI).
  144translate_message2(error(ISO, SWI)) -->
  145    swi_location(SWI),
  146    term_message(ISO),
  147    swi_extra(SWI).
  148translate_message2(unwind(Term)) -->
  149    unwind_message(Term).
  150translate_message2(message_lines(Lines), L, T) :- % deal with old C-warning()
  151    make_message_lines(Lines, L, T).
  152translate_message2(format(Fmt, Args)) -->
  153    [ Fmt-Args ].
  154
  155make_message_lines([], T, T) :- !.
  156make_message_lines([Last],  ['~w'-[Last]|T], T) :- !.
  157make_message_lines([L0|LT], ['~w'-[L0],nl|T0], T) :-
  158    make_message_lines(LT, T0, T).
 term_message(+Term)//
Deal with the formal argument of error(Format, ImplDefined) exception terms. The ImplDefined argument is handled by swi_location//2.
  166:- public term_message//1.  167term_message(Term) -->
  168    {var(Term)},
  169    !,
  170    [ 'Unknown error term: ~p'-[Term] ].
  171term_message(Term) -->
  172    { message_lang(Lang) },
  173    prolog:error_message(Lang, Term),
  174    !.
  175term_message(Term) -->
  176    prolog:error_message(Term),
  177    !.
  178term_message(Term) -->
  179    iso_message(Term).
  180term_message(Term) -->
  181    swi_message(Term).
  182term_message(Term) -->
  183    [ 'Unknown error term: ~p'-[Term] ].
  184
  185iso_message(resource_error(c_stack)) -->
  186    out_of_c_stack.
  187iso_message(resource_error(Missing)) -->
  188    [ 'Not enough resources: ~w'-[Missing] ].
  189iso_message(type_error(evaluable, Actual)) -->
  190    { callable(Actual) },
  191    [ 'Arithmetic: `~p'' is not a function'-[Actual] ].
  192iso_message(type_error(free_of_attvar, Actual)) -->
  193    [ 'Type error: `~W'' contains attributed variables'-
  194      [Actual,[portray(true), attributes(portray)]] ].
  195iso_message(type_error(Expected, Actual)) -->
  196    [ 'Type error: `~w'' expected, found `~p'''-[Expected, Actual] ],
  197    type_error_comment(Expected, Actual).
  198iso_message(domain_error(Domain, Actual)) -->
  199    [ 'Domain error: '-[] ], domain(Domain),
  200    [ ' expected, found `~p'''-[Actual] ].
  201iso_message(instantiation_error) -->
  202    [ 'Arguments are not sufficiently instantiated' ].
  203iso_message(uninstantiation_error(Var)) -->
  204    [ 'Uninstantiated argument expected, found ~p'-[Var] ].
  205iso_message(representation_error(What)) -->
  206    [ 'Cannot represent due to `~w'''-[What] ].
  207iso_message(permission_error(Action, Type, Object)) -->
  208    permission_error(Action, Type, Object).
  209iso_message(evaluation_error(Which)) -->
  210    [ 'Arithmetic: evaluation error: `~p'''-[Which] ].
  211iso_message(existence_error(procedure, Proc)) -->
  212    [ 'Unknown procedure: ~q'-[Proc] ],
  213    unknown_proc_msg(Proc).
  214iso_message(existence_error(answer_variable, Var)) -->
  215    [ '$~w was not bound by a previous query'-[Var] ].
  216iso_message(existence_error(matching_rule, Goal)) -->
  217    [ 'No rule matches ~p'-[Goal] ].
  218iso_message(existence_error(Type, Object)) -->
  219    [ '~w `~p'' does not exist'-[Type, Object] ].
  220iso_message(existence_error(export, PI, module(M))) --> % not ISO
  221    [ 'Module ', ansi(code, '~q', [M]), ' does not export ',
  222      ansi(code, '~q', [PI]) ].
  223iso_message(existence_error(Type, Object, In)) --> % not ISO
  224    [ '~w `~p'' does not exist in ~p'-[Type, Object, In] ].
  225iso_message(busy(Type, Object)) -->
  226    [ '~w `~p'' is busy'-[Type, Object] ].
  227iso_message(syntax_error(swi_backslash_newline)) -->
  228    [ 'Deprecated: ... \\<newline><white>*.  Use \\c' ].
  229iso_message(syntax_error(warning_var_tag)) -->
  230    [ 'Deprecated: dict with unbound tag (_{...}).  Mapped to #{...}.' ].
  231iso_message(syntax_error(var_tag)) -->
  232    [ 'Syntax error: dict syntax with unbound tag (_{...}).' ].
  233iso_message(syntax_error(Id)) -->
  234    [ 'Syntax error: ' ],
  235    syntax_error(Id).
  236iso_message(occurs_check(Var, In)) -->
  237    [ '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.
  244permission_error(Action, built_in_procedure, Pred) -->
  245    { user_predicate_indicator(Pred, PI)
  246    },
  247    [ 'No permission to ~w built-in predicate `~p'''-[Action, PI] ],
  248    (   {Action \== export}
  249    ->  [ nl,
  250          'Use :- redefine_system_predicate(+Head) if redefinition is intended'
  251        ]
  252    ;   []
  253    ).
  254permission_error(import_into(Dest), procedure, Pred) -->
  255    [ 'No permission to import ~p into ~w'-[Pred, Dest] ].
  256permission_error(Action, static_procedure, Proc) -->
  257    [ 'No permission to ~w static procedure `~p'''-[Action, Proc] ],
  258    defined_definition('Defined', Proc).
  259permission_error(input, stream, Stream) -->
  260    [ 'No permission to read from output stream `~p'''-[Stream] ].
  261permission_error(output, stream, Stream) -->
  262    [ 'No permission to write to input stream `~p'''-[Stream] ].
  263permission_error(input, text_stream, Stream) -->
  264    [ 'No permission to read bytes from TEXT stream `~p'''-[Stream] ].
  265permission_error(output, text_stream, Stream) -->
  266    [ 'No permission to write bytes to TEXT stream `~p'''-[Stream] ].
  267permission_error(input, binary_stream, Stream) -->
  268    [ 'No permission to read characters from binary stream `~p'''-[Stream] ].
  269permission_error(output, binary_stream, Stream) -->
  270    [ 'No permission to write characters to binary stream `~p'''-[Stream] ].
  271permission_error(open, source_sink, alias(Alias)) -->
  272    [ 'No permission to reuse alias "~p": already taken'-[Alias] ].
  273permission_error(tnot, non_tabled_procedure, Pred) -->
  274    [ 'The argument of tnot/1 is not tabled: ~p'-[Pred] ].
  275permission_error(assert, procedure, Pred) -->
  276    { '$pi_head'(Pred, Head),
  277      predicate_property(Head, ssu)
  278    },
  279    [ '~p: an SSU (Head => Body) predicate cannot have normal Prolog clauses'-
  280      [Pred] ].
  281permission_error(Action, Type, Object) -->
  282    [ 'No permission to ~w ~w `~p'''-[Action, Type, Object] ].
  283
  284
  285unknown_proc_msg(_:(^)/2) -->
  286    !,
  287    unknown_proc_msg((^)/2).
  288unknown_proc_msg((^)/2) -->
  289    !,
  290    [nl, '  ^/2 can only appear as the 2nd argument of setof/3 and bagof/3'].
  291unknown_proc_msg((:-)/2) -->
  292    !,
  293    [nl, '  Rules must be loaded from a file'],
  294    faq('ToplevelMode').
  295unknown_proc_msg((=>)/2) -->
  296    !,
  297    [nl, '  Rules must be loaded from a file'],
  298    faq('ToplevelMode').
  299unknown_proc_msg((:-)/1) -->
  300    !,
  301    [nl, '  Directives must be loaded from a file'],
  302    faq('ToplevelMode').
  303unknown_proc_msg((?-)/1) -->
  304    !,
  305    [nl, '  ?- is the Prolog prompt'],
  306    faq('ToplevelMode').
  307unknown_proc_msg(Proc) -->
  308    { dwim_predicates(Proc, Dwims) },
  309    (   {Dwims \== []}
  310    ->  [nl, '  However, there are definitions for:', nl],
  311        dwim_message(Dwims)
  312    ;   []
  313    ).
  314
  315dependency_error(shared(Shared), private(Private)) -->
  316    [ 'Shared table for ~p may not depend on private ~p'-[Shared, Private] ].
  317dependency_error(Dep, monotonic(On)) -->
  318    { '$pi_head'(PI, Dep),
  319      '$pi_head'(MPI, On)
  320    },
  321    [ 'Dependent ~p on monotonic predicate ~p is not monotonic or incremental'-
  322      [PI, MPI]
  323    ].
  324
  325faq(Page) -->
  326    [nl, '  See FAQ at https://www.swi-prolog.org/FAQ/', Page, '.html' ].
  327
  328type_error_comment(_Expected, Actual) -->
  329    { type_of(Actual, Type),
  330      (   sub_atom(Type, 0, 1, _, First),
  331          memberchk(First, [a,e,i,o,u])
  332      ->  Article = an
  333      ;   Article = a
  334      )
  335    },
  336    [ ' (~w ~w)'-[Article, Type] ].
  337
  338type_of(Term, Type) :-
  339    (   attvar(Term)      -> Type = attvar
  340    ;   var(Term)         -> Type = var
  341    ;   atom(Term)        -> Type = atom
  342    ;   integer(Term)     -> Type = integer
  343    ;   string(Term)      -> Type = string
  344    ;   Term == []        -> Type = empty_list
  345    ;   blob(Term, BlobT) -> blob_type(BlobT, Type)
  346    ;   rational(Term)    -> Type = rational
  347    ;   float(Term)       -> Type = float
  348    ;   is_stream(Term)   -> Type = stream
  349    ;   is_dict(Term)     -> Type = dict
  350    ;   is_list(Term)     -> Type = list
  351    ;   Term = [_|_]      -> list_like(Term, Type)
  352    ;   cyclic_term(Term) -> Type = cyclic
  353    ;   compound(Term)    -> Type = compound
  354    ;                        Type = unknown
  355    ).
  356
  357list_like(Term, Type) :-
  358    '$skip_list'(_, Term, Tail),
  359    (   var(Tail)
  360    ->  Type = partial_list
  361    ;   Type = invalid_list                      % TBD: Better name?
  362    ).
  363
  364blob_type(BlobT, Type) :-
  365    atom_concat(BlobT, '_reference', Type).
  366
  367syntax_error(end_of_clause) -->
  368    [ 'Unexpected end of clause' ].
  369syntax_error(end_of_clause_expected) -->
  370    [ 'End of clause expected' ].
  371syntax_error(end_of_file) -->
  372    [ 'Unexpected end of file' ].
  373syntax_error(end_of_file_in_block_comment) -->
  374    [ 'End of file in /* ... */ comment' ].
  375syntax_error(end_of_file_in_quoted(Quote)) -->
  376    [ 'End of file in quoted ' ],
  377    quoted_type(Quote).
  378syntax_error(illegal_number) -->
  379    [ 'Illegal number' ].
  380syntax_error(long_atom) -->
  381    [ 'Atom too long (see style_check/1)' ].
  382syntax_error(long_string) -->
  383    [ 'String too long (see style_check/1)' ].
  384syntax_error(operator_clash) -->
  385    [ 'Operator priority clash' ].
  386syntax_error(operator_expected) -->
  387    [ 'Operator expected' ].
  388syntax_error(operator_balance) -->
  389    [ 'Unbalanced operator' ].
  390syntax_error(quoted_punctuation) -->
  391    [ 'Operand expected, unquoted comma or bar found' ].
  392syntax_error(list_rest) -->
  393    [ 'Unexpected comma or bar in rest of list' ].
  394syntax_error(cannot_start_term) -->
  395    [ 'Illegal start of term' ].
  396syntax_error(punct(Punct, End)) -->
  397    [ 'Unexpected `~w\' before `~w\''-[Punct, End] ].
  398syntax_error(undefined_char_escape(C)) -->
  399    [ 'Unknown character escape in quoted atom or string: `\\~w\''-[C] ].
  400syntax_error(void_not_allowed) -->
  401    [ 'Empty argument list "()"' ].
  402syntax_error(Term) -->
  403    { compound(Term),
  404      compound_name_arguments(Term, Syntax, [Text])
  405    }, !,
  406    [ '~w expected, found '-[Syntax], ansi(code, '"~w"', [Text]) ].
  407syntax_error(Message) -->
  408    [ '~w'-[Message] ].
  409
  410quoted_type('\'') --> [atom].
  411quoted_type('\"') --> { current_prolog_flag(double_quotes, Type) }, [Type-[]].
  412quoted_type('\`') --> { current_prolog_flag(back_quotes, Type) }, [Type-[]].
  413
  414domain(range(Low,High)) -->
  415    !,
  416    ['[~q..~q]'-[Low,High] ].
  417domain(Domain) -->
  418    ['`~w\''-[Domain] ].
 tabling_existence_error(+Ball, +Context)//
Called on invalid shift/1 calls. Track those that result from tabling errors.
  425tabling_existence_error(Ball, Context) -->
  426    { table_shift_ball(Ball) },
  427    [ 'Tabling dependency error' ],
  428    swi_extra(Context).
  429
  430table_shift_ball(dependency(_Head)).
  431table_shift_ball(dependency(_Skeleton, _Trie, _Mono)).
  432table_shift_ball(call_info(_Skeleton, _Status)).
  433table_shift_ball(call_info(_GenSkeleton, _Skeleton, _Status)).
 dwim_predicates(+PI, -Dwims)
Find related predicate indicators.
  439dwim_predicates(Module:Name/_Arity, Dwims) :-
  440    !,
  441    findall(Dwim, dwim_predicate(Module:Name, Dwim), Dwims).
  442dwim_predicates(Name/_Arity, Dwims) :-
  443    findall(Dwim, dwim_predicate(user:Name, Dwim), Dwims).
  444
  445dwim_message([]) --> [].
  446dwim_message([M:Head|T]) -->
  447    { hidden_module(M),
  448      !,
  449      functor(Head, Name, Arity)
  450    },
  451    [ '        ~q'-[Name/Arity], nl ],
  452    dwim_message(T).
  453dwim_message([Module:Head|T]) -->
  454    !,
  455    { functor(Head, Name, Arity)
  456    },
  457    [ '        ~q'-[Module:Name/Arity], nl],
  458    dwim_message(T).
  459dwim_message([Head|T]) -->
  460    {functor(Head, Name, Arity)},
  461    [ '        ~q'-[Name/Arity], nl],
  462    dwim_message(T).
  463
  464
  465swi_message(io_error(Op, Stream)) -->
  466    [ 'I/O error in ~w on stream ~p'-[Op, Stream] ].
  467swi_message(thread_error(TID, false)) -->
  468    [ 'Thread ~p died due to failure:'-[TID] ].
  469swi_message(thread_error(TID, exception(Error))) -->
  470    [ 'Thread ~p died abnormally:'-[TID], nl ],
  471    translate_message(Error).
  472swi_message(dependency_error(Tabled, DependsOn)) -->
  473    dependency_error(Tabled, DependsOn).
  474swi_message(shell(execute, Cmd)) -->
  475    [ 'Could not execute `~w'''-[Cmd] ].
  476swi_message(shell(signal(Sig), Cmd)) -->
  477    [ 'Caught signal ~d on `~w'''-[Sig, Cmd] ].
  478swi_message(format(Fmt, Args)) -->
  479    [ Fmt-Args ].
  480swi_message(signal(Name, Num)) -->
  481    [ 'Caught signal ~d (~w)'-[Num, Name] ].
  482swi_message(limit_exceeded(Limit, MaxVal)) -->
  483    [ 'Exceeded ~w limit (~w)'-[Limit, MaxVal] ].
  484swi_message(goal_failed(Goal)) -->
  485    [ 'goal unexpectedly failed: ~p'-[Goal] ].
  486swi_message(shared_object(_Action, Message)) --> % Message = dlerror()
  487    [ '~w'-[Message] ].
  488swi_message(system_error(Error)) -->
  489    [ 'error in system call: ~w'-[Error]
  490    ].
  491swi_message(system_error) -->
  492    [ 'error in system call'
  493    ].
  494swi_message(failure_error(Goal)) -->
  495    [ 'Goal failed: ~p'-[Goal] ].
  496swi_message(timeout_error(Op, Stream)) -->
  497    [ 'Timeout in ~w from ~p'-[Op, Stream] ].
  498swi_message(not_implemented(Type, What)) -->
  499    [ '~w `~p\' is not implemented in this version'-[Type, What] ].
  500swi_message(context_error(nodirective, Goal)) -->
  501    { goal_to_predicate_indicator(Goal, PI) },
  502    [ 'Wrong context: ~p can only be used in a directive'-[PI] ].
  503swi_message(context_error(edit, no_default_file)) -->
  504    (   { current_prolog_flag(windows, true) }
  505    ->  [ 'Edit/0 can only be used after opening a \c
  506               Prolog file by double-clicking it' ]
  507    ;   [ 'Edit/0 can only be used with the "-s file" commandline option'
  508        ]
  509    ),
  510    [ nl, 'Use "?- edit(Topic)." or "?- emacs."' ].
  511swi_message(context_error(function, meta_arg(S))) -->
  512    [ 'Functions are not (yet) supported for meta-arguments of type ~q'-[S] ].
  513swi_message(format_argument_type(Fmt, Arg)) -->
  514    [ 'Illegal argument to format sequence ~~~w: ~p'-[Fmt, Arg] ].
  515swi_message(format(Msg)) -->
  516    [ 'Format error: ~w'-[Msg] ].
  517swi_message(conditional_compilation_error(unterminated, File:Line)) -->
  518    [ 'Unterminated conditional compilation from '-[], url(File:Line) ].
  519swi_message(conditional_compilation_error(no_if, What)) -->
  520    [ ':- ~w without :- if'-[What] ].
  521swi_message(duplicate_key(Key)) -->
  522    [ 'Duplicate key: ~p'-[Key] ].
  523swi_message(determinism_error(PI, det, Found, property)) -->
  524    (   { '$pi_head'(user:PI, Head),
  525          predicate_property(Head, det)
  526        }
  527    ->  [ 'Deterministic procedure ~p'-[PI] ]
  528    ;   [ 'Procedure ~p called from a deterministic procedure'-[PI] ]
  529    ),
  530    det_error(Found).
  531swi_message(determinism_error(PI, det, fail, guard)) -->
  532    [ 'Procedure ~p failed after $-guard'-[PI] ].
  533swi_message(determinism_error(PI, det, fail, guard_in_caller)) -->
  534    [ 'Procedure ~p failed after $-guard in caller'-[PI] ].
  535swi_message(determinism_error(Goal, det, fail, goal)) -->
  536    [ 'Goal ~p failed'-[Goal] ].
  537swi_message(determinism_error(Goal, det, nondet, goal)) -->
  538    [ 'Goal ~p succeeded with a choice point'-[Goal] ].
  539swi_message(qlf_format_error(File, Message)) -->
  540    [ '~w: Invalid QLF file: ~w'-[File, Message] ].
  541swi_message(goal_expansion_error(bound, Term)) -->
  542    [ 'Goal expansion bound a variable to ~p'-[Term] ].
  543
  544det_error(nondet) -->
  545    [ ' succeeded with a choicepoint'- [] ].
  546det_error(fail) -->
  547    [ ' failed'- [] ].
 swi_location(+Term)// is det
Print location information for error(Formal, ImplDefined) from the ImplDefined term.
  555:- public swi_location//1.  556swi_location(X) -->
  557    { var(X) },
  558    !.
  559swi_location(Context) -->
  560    { message_lang(Lang) },
  561    prolog:message_location(Lang, Context),
  562    !.
  563swi_location(Context) -->
  564    prolog:message_location(Context),
  565    !.
  566swi_location(context(Caller, _Msg)) -->
  567    { ground(Caller) },
  568    !,
  569    caller(Caller).
  570swi_location(file(Path, Line, -1, _CharNo)) -->
  571    !,
  572    [ url(Path:Line), ': ' ].
  573swi_location(file(Path, Line, LinePos, _CharNo)) -->
  574    [ url(Path:Line:LinePos), ': ' ].
  575swi_location(stream(Stream, Line, LinePos, CharNo)) -->
  576    (   { is_stream(Stream),
  577          stream_property(Stream, file_name(File))
  578        }
  579    ->  swi_location(file(File, Line, LinePos, CharNo))
  580    ;   [ 'Stream ~w:~d:~d '-[Stream, Line, LinePos] ]
  581    ).
  582swi_location(autoload(File:Line)) -->
  583    [ url(File:Line), ': ' ].
  584swi_location(_) -->
  585    [].
  586
  587caller(system:'$record_clause'/3) -->
  588    !,
  589    [].
  590caller(Module:Name/Arity) -->
  591    !,
  592    (   { \+ hidden_module(Module) }
  593    ->  [ '~q:~q/~w: '-[Module, Name, Arity] ]
  594    ;   [ '~q/~w: '-[Name, Arity] ]
  595    ).
  596caller(Name/Arity) -->
  597    [ '~q/~w: '-[Name, Arity] ].
  598caller(Caller) -->
  599    [ '~p: '-[Caller] ].
 swi_extra(+Term)// is det
Extract information from the second argument of an error(Formal, ImplDefined) that is printed after the core of the message.
See also
- swi_location//1 uses the same term to insert context before the core of the message.
  610swi_extra(X) -->
  611    { var(X) },
  612    !,
  613    [].
  614swi_extra(Context) -->
  615    { message_lang(Lang) },
  616    prolog:message_context(Lang, Context),
  617    !.
  618swi_extra(Context) -->
  619    prolog:message_context(Context).
  620swi_extra(context(_, Msg)) -->
  621    { nonvar(Msg),
  622      Msg \== ''
  623    },
  624    !,
  625    swi_comment(Msg).
  626swi_extra(string(String, CharPos)) -->
  627    { sub_string(String, 0, CharPos, _, Before),
  628      sub_string(String, CharPos, _, 0, After)
  629    },
  630    [ nl, '~w'-[Before], nl, '** here **', nl, '~w'-[After] ].
  631swi_extra(_) -->
  632    [].
  633
  634swi_comment(already_from(Module)) -->
  635    !,
  636    [ ' (already imported from ~q)'-[Module] ].
  637swi_comment(directory(_Dir)) -->
  638    !,
  639    [ ' (is a directory)' ].
  640swi_comment(not_a_directory(_Dir)) -->
  641    !,
  642    [ ' (is not a directory)' ].
  643swi_comment(Msg) -->
  644    [ ' (~w)'-[Msg] ].
  645
  646
  647thread_context -->
  648    { \+ current_prolog_flag(toplevel_thread, true),
  649      thread_self(Id)
  650    },
  651    !,
  652    ['[Thread ~w] '-[Id]].
  653thread_context -->
  654    [].
  655
  656		 /*******************************
  657		 *        UNWIND MESSAGES	*
  658		 *******************************/
  659
  660unwind_message(Var) -->
  661    { var(Var) }, !,
  662    [ 'Unknown unwind message: ~p'-[Var] ].
  663unwind_message(abort) -->
  664    [ 'Execution Aborted' ].
  665unwind_message(halt(_)) -->
  666    [].
  667unwind_message(thread_exit(Term)) -->
  668    [ 'Invalid thread_exit/1.  Payload: ~p'-[Term] ].
  669unwind_message(Term) -->
  670    [ 'Unknown "unwind" exception: ~p'-[Term] ].
  671
  672
  673                 /*******************************
  674                 *        NORMAL MESSAGES       *
  675                 *******************************/
  676
  677:- dynamic prolog:version_msg/1.  678:- multifile prolog:version_msg/1.  679
  680prolog_message(welcome) -->
  681    [ 'Welcome to SWI-Prolog (' ],
  682    prolog_message(threads),
  683    prolog_message(address_bits),
  684    ['version ' ],
  685    prolog_message(version),
  686    [ ')', nl ],
  687    prolog_message(copyright),
  688    [ nl ],
  689    translate_message(user_versions),
  690    [ nl ],
  691    prolog_message(documentaton),
  692    [ nl, nl ].
  693prolog_message(user_versions) -->
  694    (   { findall(Msg, prolog:version_msg(Msg), Msgs),
  695          Msgs \== []
  696        }
  697    ->  [nl],
  698        user_version_messages(Msgs)
  699    ;   []
  700    ).
  701prolog_message(deprecated(Term)) -->
  702    { nonvar(Term) },
  703    (   { message_lang(Lang) },
  704        prolog:deprecated(Lang, Term)
  705    ->  []
  706    ;   prolog:deprecated(Term)
  707    ->  []
  708    ;   deprecated(Term)
  709    ).
  710prolog_message(unhandled_exception(E)) -->
  711    { nonvar(E) },
  712    [ 'Unhandled exception: ' ],
  713    (   translate_message(E)
  714    ->  []
  715    ;   [ '~p'-[E] ]
  716    ).
 prolog_message(+Term)//
  720prolog_message(initialization_error(_, E, File:Line)) -->
  721    !,
  722    [ url(File:Line),
  723      ': Initialization goal raised exception:', nl
  724    ],
  725    translate_message(E).
  726prolog_message(initialization_error(Goal, E, _)) -->
  727    [ 'Initialization goal ~p raised exception:'-[Goal], nl ],
  728    translate_message(E).
  729prolog_message(initialization_failure(_Goal, File:Line)) -->
  730    !,
  731    [ url(File:Line),
  732      ': Initialization goal failed'-[]
  733    ].
  734prolog_message(initialization_failure(Goal, _)) -->
  735    [ 'Initialization goal failed: ~p'-[Goal]
  736    ].
  737prolog_message(initialization_exception(E)) -->
  738    [ 'Prolog initialisation failed:', nl ],
  739    translate_message(E).
  740prolog_message(initialization(halt(Status), Goal, File:Line)) -->
  741    [ url(File:Line), ': '], goal(Goal), [nl,
  742      '  Initialization goal called ', ansi(code, '~p', [halt(Status)]),
  743      '.', nl,
  744      '  The program entry point should be called using ',
  745      ansi(code, 'initialization/2', []), '.', nl,
  746      '  Consider using ', ansi(code, 'library(main)', []), '.'
  747    ].
  748prolog_message(init_goal_syntax(Error, Text)) -->
  749    !,
  750    [ '-g ~w: '-[Text] ],
  751    translate_message(Error).
  752prolog_message(init_goal_failed(failed, @(Goal,File:Line))) -->
  753    !,
  754    [ url(File:Line), ': ~p: false'-[Goal] ].
  755prolog_message(init_goal_failed(Error, @(Goal,File:Line))) -->
  756    !,
  757    [ url(File:Line), ': ~p '-[Goal] ],
  758    translate_message(Error).
  759prolog_message(init_goal_failed(failed, Text)) -->
  760    !,
  761    [ '-g ~w: false'-[Text] ].
  762prolog_message(init_goal_failed(Error, Text)) -->
  763    !,
  764    [ '-g ~w: '-[Text] ],
  765    translate_message(Error).
  766prolog_message(goal_failed(Context, Goal)) -->
  767    [ 'Goal (~w) failed: ~p'-[Context, Goal] ].
  768prolog_message(no_current_module(Module)) -->
  769    [ '~w is not a current module (created)'-[Module] ].
  770prolog_message(commandline_arg_type(Flag, Arg)) -->
  771    [ 'Bad argument to commandline option -~w: ~w'-[Flag, Arg] ].
  772prolog_message(missing_feature(Name)) -->
  773    [ 'This version of SWI-Prolog does not support ~w'-[Name] ].
  774prolog_message(singletons(_Term, List)) -->
  775    [ 'Singleton variables: ~w'-[List] ].
  776prolog_message(multitons(_Term, List)) -->
  777    [ 'Singleton-marked variables appearing more than once: ~w'-[List] ].
  778prolog_message(profile_no_cpu_time) -->
  779    [ 'No CPU-time info.  Check the SWI-Prolog manual for details' ].
  780prolog_message(non_ascii(Text, Type)) -->
  781    [ 'Unquoted ~w with non-portable characters: ~w'-[Type, Text] ].
  782prolog_message(io_warning(Stream, Message)) -->
  783    { stream_property(Stream, position(Position)),
  784      !,
  785      stream_position_data(line_count, Position, LineNo),
  786      stream_position_data(line_position, Position, LinePos),
  787      (   stream_property(Stream, file_name(File))
  788      ->  Obj = File
  789      ;   Obj = Stream
  790      )
  791    },
  792    [ '~p:~d:~d: ~w'-[Obj, LineNo, LinePos, Message] ].
  793prolog_message(io_warning(Stream, Message)) -->
  794    [ 'stream ~p: ~w'-[Stream, Message] ].
  795prolog_message(option_usage(pldoc)) -->
  796    [ 'Usage: --pldoc[=port]' ].
  797prolog_message(interrupt(begin)) -->
  798    [ 'Action (h for help) ? ', flush ].
  799prolog_message(interrupt(end)) -->
  800    [ 'continue' ].
  801prolog_message(interrupt(trace)) -->
  802    [ 'continue (trace mode)' ].
  803prolog_message(unknown_in_module_user) -->
  804    [ 'Using a non-error value for unknown in the global module', nl,
  805      'causes most of the development environment to stop working.', nl,
  806      'Please use :- dynamic or limit usage of unknown to a module.', nl,
  807      'See https://www.swi-prolog.org/howto/database.html'
  808    ].
  809prolog_message(untable(PI)) -->
  810    [ 'Reconsult: removed tabling for ~p'-[PI] ].
  811prolog_message(unknown_option(Set, Opt)) -->
  812    [ 'Unknown ~w option: ~p'-[Set, Opt] ].
  813
  814
  815                 /*******************************
  816                 *         LOADING FILES        *
  817                 *******************************/
  818
  819prolog_message(modify_active_procedure(Who, What)) -->
  820    [ '~p: modified active procedure ~p'-[Who, What] ].
  821prolog_message(load_file(failed(user:File))) -->
  822    [ 'Failed to load ~p'-[File] ].
  823prolog_message(load_file(failed(Module:File))) -->
  824    [ 'Failed to load ~p into module ~p'-[File, Module] ].
  825prolog_message(load_file(failed(File))) -->
  826    [ 'Failed to load ~p'-[File] ].
  827prolog_message(mixed_directive(Goal)) -->
  828    [ 'Cannot pre-compile mixed load/call directive: ~p'-[Goal] ].
  829prolog_message(cannot_redefine_comma) -->
  830    [ 'Full stop in clause-body?  Cannot redefine ,/2' ].
  831prolog_message(illegal_autoload_index(Dir, Term)) -->
  832    [ 'Illegal term in INDEX file of directory ~w: ~w'-[Dir, Term] ].
  833prolog_message(redefined_procedure(Type, Proc)) -->
  834    [ 'Redefined ~w procedure ~p'-[Type, Proc] ],
  835    defined_definition('Previously defined', Proc).
  836prolog_message(declare_module(Module, abolish(Predicates))) -->
  837    [ 'Loading module ~w abolished: ~p'-[Module, Predicates] ].
  838prolog_message(import_private(Module, Private)) -->
  839    [ 'import/1: ~p is not exported (still imported into ~q)'-
  840      [Private, Module]
  841    ].
  842prolog_message(ignored_weak_import(Into, From:PI)) -->
  843    [ 'Local definition of ~p overrides weak import from ~q'-
  844      [Into:PI, From]
  845    ].
  846prolog_message(undefined_export(Module, PI)) -->
  847    [ 'Exported procedure ~q:~q is not defined'-[Module, PI] ].
  848prolog_message(no_exported_op(Module, Op)) -->
  849    [ 'Operator ~q:~q is not exported (still defined)'-[Module, Op] ].
  850prolog_message(discontiguous((-)/2,_)) -->
  851    prolog_message(minus_in_identifier).
  852prolog_message(discontiguous(Proc,Current)) -->
  853    [ 'Clauses of ', ansi(code, '~p', [Proc]),
  854      ' are not together in the source-file', nl ],
  855    current_definition(Proc, 'Earlier definition at '),
  856    [ 'Current predicate: ', ansi(code, '~p', [Current]), nl,
  857      'Use ', ansi(code, ':- discontiguous ~p.', [Proc]),
  858      ' to suppress this message'
  859    ].
  860prolog_message(decl_no_effect(Goal)) -->
  861    [ 'Deprecated declaration has no effect: ~p'-[Goal] ].
  862prolog_message(load_file(start(Level, File))) -->
  863    [ '~|~t~*+Loading '-[Level] ],
  864    load_file(File),
  865    [ ' ...' ].
  866prolog_message(include_file(start(Level, File))) -->
  867    [ '~|~t~*+include '-[Level] ],
  868    load_file(File),
  869    [ ' ...' ].
  870prolog_message(include_file(done(Level, File))) -->
  871    [ '~|~t~*+included '-[Level] ],
  872    load_file(File).
  873prolog_message(load_file(done(Level, File, Action, Module, Time, Clauses))) -->
  874    [ '~|~t~*+'-[Level] ],
  875    load_file(File),
  876    [ ' ~w'-[Action] ],
  877    load_module(Module),
  878    [ ' ~2f sec, ~D clauses'-[Time, Clauses] ].
  879prolog_message(dwim_undefined(Goal, Alternatives)) -->
  880    { goal_to_predicate_indicator(Goal, Pred)
  881    },
  882    [ 'Unknown procedure: ~q'-[Pred], nl,
  883      '    However, there are definitions for:', nl
  884    ],
  885    dwim_message(Alternatives).
  886prolog_message(dwim_correct(Into)) -->
  887    [ 'Correct to: ~q? '-[Into], flush ].
  888prolog_message(error(loop_error(Spec), file_search(Used))) -->
  889    [ 'File search: too many levels of indirections on: ~p'-[Spec], nl,
  890      '    Used alias expansions:', nl
  891    ],
  892    used_search(Used).
  893prolog_message(minus_in_identifier) -->
  894    [ 'The "-" character should not be used to separate words in an', nl,
  895      'identifier.  Check the SWI-Prolog FAQ for details.'
  896    ].
  897prolog_message(qlf(removed_after_error(File))) -->
  898    [ 'Removed incomplete QLF file ~w'-[File] ].
  899prolog_message(qlf(recompile(Spec,_Pl,_Qlf,Reason))) -->
  900    [ '~p: recompiling QLF file'-[Spec] ],
  901    qlf_recompile_reason(Reason).
  902prolog_message(qlf(can_not_recompile(Spec,QlfFile,_Reason))) -->
  903    [ '~p: can not recompile "~w" (access denied)'-[Spec, QlfFile], nl,
  904      '\tLoading from source'-[]
  905    ].
  906prolog_message(qlf(system_lib_out_of_date(Spec,QlfFile))) -->
  907    [ '~p: can not recompile "~w" (access denied)'-[Spec, QlfFile], nl,
  908      '\tLoading QlfFile'-[]
  909    ].
  910prolog_message(redefine_module(Module, OldFile, File)) -->
  911    [ 'Module "~q" already loaded from ~w.'-[Module, OldFile], nl,
  912      'Wipe and reload from ~w? '-[File], flush
  913    ].
  914prolog_message(redefine_module_reply) -->
  915    [ 'Please answer y(es), n(o) or a(bort)' ].
  916prolog_message(reloaded_in_module(Absolute, OldContext, LM)) -->
  917    [ '~w was previously loaded in module ~w'-[Absolute, OldContext], nl,
  918      '\tnow it is reloaded into module ~w'-[LM] ].
  919prolog_message(expected_layout(Expected, Pos)) -->
  920    [ 'Layout data: expected ~w, found: ~p'-[Expected, Pos] ].
  921
  922defined_definition(Message, Spec) -->
  923    { strip_module(user:Spec, M, Name/Arity),
  924      functor(Head, Name, Arity),
  925      predicate_property(M:Head, file(File)),
  926      predicate_property(M:Head, line_count(Line))
  927    },
  928    !,
  929    [ nl, '~w at '-[Message], url(File:Line) ].
  930defined_definition(_, _) --> [].
  931
  932used_search([]) -->
  933    [].
  934used_search([Alias=Expanded|T]) -->
  935    [ '        file_search_path(~p, ~p)'-[Alias, Expanded], nl ],
  936    used_search(T).
  937
  938load_file(file(Spec, _Path)) -->
  939    (   {atomic(Spec)}
  940    ->  [ '~w'-[Spec] ]
  941    ;   [ '~p'-[Spec] ]
  942    ).
  943%load_file(file(_, Path)) -->
  944%       [ '~w'-[Path] ].
  945
  946load_module(user) --> !.
  947load_module(system) --> !.
  948load_module(Module) -->
  949    [ ' into ~w'-[Module] ].
  950
  951goal_to_predicate_indicator(Goal, PI) :-
  952    strip_module(Goal, Module, Head),
  953    '$pi_head'(PI0, Module:Head),
  954    (   current_predicate(PI0),
  955        predicate_property(Module:Head, non_terminal)
  956    ->  dcg_pi(PI0, PI)
  957    ;   PI = PI0
  958    ),
  959    user_predicate_indicator(PI, PI).
  960
  961dcg_pi(Module:Name/Arity, Module:Name//DCGArity) :-
  962    DCGArity is Arity-2.
  963
  964user_predicate_indicator(Module:PI, PI) :-
  965    hidden_module(Module),
  966    !.
  967user_predicate_indicator(PI, PI).
  968
  969hidden_module(user) :- !.
  970hidden_module(system) :- !.
  971hidden_module(M) :-
  972    sub_atom(M, 0, _, _, $).
  973
  974current_definition(Proc, Prefix) -->
  975    { pi_uhead(Proc, Head),
  976      predicate_property(Head, file(File)),
  977      predicate_property(Head, line_count(Line))
  978    },
  979    [ '~w'-[Prefix], url(File:Line), nl ].
  980current_definition(_, _) --> [].
  981
  982pi_uhead(Module:Name/Arity, Module:Head) :-
  983    !,
  984    atom(Module), atom(Name), integer(Arity),
  985    functor(Head, Name, Arity).
  986pi_uhead(Name/Arity, user:Head) :-
  987    atom(Name), integer(Arity),
  988    functor(Head, Name, Arity).
  989
  990qlf_recompile_reason(old) -->
  991    !,
  992    [ ' (out of date)'-[] ].
  993qlf_recompile_reason(_) -->
  994    [ ' (incompatible with current Prolog version)'-[] ].
  995
  996prolog_message(file_search(cache(Spec, _Cond), Path)) -->
  997    [ 'File search: ~p --> ~p (cache)'-[Spec, Path] ].
  998prolog_message(file_search(found(Spec, Cond), Path)) -->
  999    [ 'File search: ~p --> ~p OK ~p'-[Spec, Path, Cond] ].
 1000prolog_message(file_search(tried(Spec, Cond), Path)) -->
 1001    [ 'File search: ~p --> ~p NO ~p'-[Spec, Path, Cond] ].
 1002
 1003                 /*******************************
 1004                 *              GC              *
 1005                 *******************************/
 1006
 1007prolog_message(agc(start)) -->
 1008    thread_context,
 1009    [ 'AGC: ', flush ].
 1010prolog_message(agc(done(Collected, Remaining, Time))) -->
 1011    [ at_same_line,
 1012      'reclaimed ~D atoms in ~3f sec. (remaining: ~D)'-
 1013      [Collected, Time, Remaining]
 1014    ].
 1015prolog_message(cgc(start)) -->
 1016    thread_context,
 1017    [ 'CGC: ', flush ].
 1018prolog_message(cgc(done(CollectedClauses, _CollectedBytes,
 1019                        RemainingBytes, Time))) -->
 1020    [ at_same_line,
 1021      'reclaimed ~D clauses in ~3f sec. (pending: ~D bytes)'-
 1022      [CollectedClauses, Time, RemainingBytes]
 1023    ].
 1024
 1025		 /*******************************
 1026		 *        STACK OVERFLOW	*
 1027		 *******************************/
 1028
 1029out_of_stack(Context) -->
 1030    { human_stack_size(Context.localused,   Local),
 1031      human_stack_size(Context.globalused,  Global),
 1032      human_stack_size(Context.trailused,   Trail),
 1033      human_stack_size(Context.stack_limit, Limit),
 1034      LCO is (100*(Context.depth - Context.environments))/Context.depth
 1035    },
 1036    [ 'Stack limit (~s) exceeded'-[Limit], nl,
 1037      '  Stack sizes: local: ~s, global: ~s, trail: ~s'-[Local,Global,Trail], nl,
 1038      '  Stack depth: ~D, last-call: ~0f%, Choice points: ~D'-
 1039         [Context.depth, LCO, Context.choicepoints], nl
 1040    ],
 1041    overflow_reason(Context, Resolve),
 1042    resolve_overflow(Resolve).
 1043
 1044human_stack_size(Size, String) :-
 1045    Size < 100,
 1046    format(string(String), '~dKb', [Size]).
 1047human_stack_size(Size, String) :-
 1048    Size < 100 000,
 1049    Value is Size / 1024,
 1050    format(string(String), '~1fMb', [Value]).
 1051human_stack_size(Size, String) :-
 1052    Value is Size / (1024*1024),
 1053    format(string(String), '~1fGb', [Value]).
 1054
 1055overflow_reason(Context, fix) -->
 1056    show_non_termination(Context),
 1057    !.
 1058overflow_reason(Context, enlarge) -->
 1059    { Stack = Context.get(stack) },
 1060    !,
 1061    [ '  In:'-[], nl ],
 1062    stack(Stack).
 1063overflow_reason(_Context, enlarge) -->
 1064    [ '  Insufficient global stack'-[] ].
 1065
 1066show_non_termination(Context) -->
 1067    (   { Stack = Context.get(cycle) }
 1068    ->  [ '  Probable infinite recursion (cycle):'-[], nl ]
 1069    ;   { Stack = Context.get(non_terminating) }
 1070    ->  [ '  Possible non-terminating recursion:'-[], nl ]
 1071    ),
 1072    stack(Stack).
 1073
 1074stack([]) --> [].
 1075stack([frame(Depth, M:Goal, _)|T]) -->
 1076    [ '    [~D] ~q:'-[Depth, M] ],
 1077    stack_goal(Goal),
 1078    [ nl ],
 1079    stack(T).
 1080
 1081stack_goal(Goal) -->
 1082    { compound(Goal),
 1083      !,
 1084      compound_name_arity(Goal, Name, Arity)
 1085    },
 1086    [ '~q('-[Name] ],
 1087    stack_goal_args(1, Arity, Goal),
 1088    [ ')'-[] ].
 1089stack_goal(Goal) -->
 1090    [ '~q'-[Goal] ].
 1091
 1092stack_goal_args(I, Arity, Goal) -->
 1093    { I =< Arity,
 1094      !,
 1095      arg(I, Goal, A),
 1096      I2 is I + 1
 1097    },
 1098    stack_goal_arg(A),
 1099    (   { I2 =< Arity }
 1100    ->  [ ', '-[] ],
 1101        stack_goal_args(I2, Arity, Goal)
 1102    ;   []
 1103    ).
 1104stack_goal_args(_, _, _) -->
 1105    [].
 1106
 1107stack_goal_arg(A) -->
 1108    { nonvar(A),
 1109      A = [Len|T],
 1110      !
 1111    },
 1112    (   {Len == cyclic_term}
 1113    ->  [ '[cyclic list]'-[] ]
 1114    ;   {T == []}
 1115    ->  [ '[length:~D]'-[Len] ]
 1116    ;   [ '[length:~D|~p]'-[Len, T] ]
 1117    ).
 1118stack_goal_arg(A) -->
 1119    { nonvar(A),
 1120      A = _/_,
 1121      !
 1122    },
 1123    [ '<compound ~p>'-[A] ].
 1124stack_goal_arg(A) -->
 1125    [ '~p'-[A] ].
 1126
 1127resolve_overflow(fix) -->
 1128    [].
 1129resolve_overflow(enlarge) -->
 1130    { current_prolog_flag(stack_limit, LimitBytes),
 1131      NewLimit is LimitBytes * 2
 1132    },
 1133    [ nl,
 1134      'Use the --stack_limit=size[KMG] command line option or'-[], nl,
 1135      '?- set_prolog_flag(stack_limit, ~I). to double the limit.'-[NewLimit]
 1136    ].
 out_of_c_stack
The thread's C-stack limit was exceeded. Give some advice on how to resolve this.
 1143out_of_c_stack -->
 1144    { statistics(c_stack, Limit), Limit > 0 },
 1145    !,
 1146    [ 'C-stack limit (~D bytes) exceeded.'-[Limit], nl ],
 1147    resolve_c_stack_overflow(Limit).
 1148out_of_c_stack -->
 1149    { statistics(c_stack, Limit), Limit > 0 },
 1150    [ 'C-stack limit exceeded.'-[Limit], nl ],
 1151    resolve_c_stack_overflow(Limit).
 1152
 1153resolve_c_stack_overflow(_Limit) -->
 1154    { thread_self(main) },
 1155    [ 'Use the shell command ' ], code('~w', 'ulimit -s size'),
 1156    [ ' to enlarge the limit.' ].
 1157resolve_c_stack_overflow(_Limit) -->
 1158    [ 'Use the ' ], code('~w', 'c_stack(KBytes)'),
 1159    [ ' option of '], code(thread_create/3), [' to enlarge the limit.' ].
 1160
 1161
 1162                 /*******************************
 1163                 *        MAKE/AUTOLOAD         *
 1164                 *******************************/
 1165
 1166prolog_message(make(reload(Files))) -->
 1167    { length(Files, N)
 1168    },
 1169    [ 'Make: reloading ~D files'-[N] ].
 1170prolog_message(make(done(_Files))) -->
 1171    [ 'Make: finished' ].
 1172prolog_message(make(library_index(Dir))) -->
 1173    [ 'Updating index for library ~w'-[Dir] ].
 1174prolog_message(autoload(Pred, File)) -->
 1175    thread_context,
 1176    [ 'autoloading ~p from ~w'-[Pred, File] ].
 1177prolog_message(autoload(read_index(Dir))) -->
 1178    [ 'Loading autoload index for ~w'-[Dir] ].
 1179prolog_message(autoload(disabled(Loaded))) -->
 1180    [ 'Disabled autoloading (loaded ~D files)'-[Loaded] ].
 1181prolog_message(autoload(already_defined(PI, From))) -->
 1182    code(PI),
 1183    (   { '$pi_head'(PI, Head),
 1184          predicate_property(Head, built_in)
 1185        }
 1186    ->  [' is a built-in predicate']
 1187    ;   [ ' is already imported from module ' ],
 1188        code(From)
 1189    ).
 1190
 1191swi_message(autoload(Msg)) -->
 1192    [ nl, '  ' ],
 1193    autoload_message(Msg).
 1194
 1195autoload_message(not_exported(PI, Spec, _FullFile, _Exports)) -->
 1196    [ ansi(code, '~w', [Spec]),
 1197      ' does not export ',
 1198      ansi(code, '~p', [PI])
 1199    ].
 1200autoload_message(no_file(Spec)) -->
 1201    [ ansi(code, '~p', [Spec]), ': No such file' ].
 1202
 1203
 1204                 /*******************************
 1205                 *       COMPILER WARNINGS      *
 1206                 *******************************/
 1207
 1208% print warnings about dubious code raised by the compiler.
 1209% TBD: pass in PC to produce exact error locations.
 1210
 1211prolog_message(compiler_warnings(Clause, Warnings0)) -->
 1212    {   print_goal_options(DefOptions),
 1213        (   prolog_load_context(variable_names, VarNames)
 1214        ->  warnings_with_named_vars(Warnings0, VarNames, Warnings),
 1215            Options = [variable_names(VarNames)|DefOptions]
 1216        ;   Options = DefOptions,
 1217            Warnings = Warnings0
 1218        )
 1219    },
 1220    compiler_warnings(Warnings, Clause, Options).
 1221
 1222warnings_with_named_vars([], _, []).
 1223warnings_with_named_vars([H|T0], VarNames, [H|T]) :-
 1224    term_variables(H, Vars),
 1225    '$member'(V1, Vars),
 1226    '$member'(_=V2, VarNames),
 1227    V1 == V2,
 1228    !,
 1229    warnings_with_named_vars(T0, VarNames, T).
 1230warnings_with_named_vars([_|T0], VarNames, T) :-
 1231    warnings_with_named_vars(T0, VarNames, T).
 1232
 1233
 1234compiler_warnings([], _, _) --> [].
 1235compiler_warnings([H|T], Clause, Options) -->
 1236    (   compiler_warning(H, Clause, Options)
 1237    ->  []
 1238    ;   [ 'Unknown compiler warning: ~W'-[H,Options] ]
 1239    ),
 1240    (   {T==[]}
 1241    ->  []
 1242    ;   [nl]
 1243    ),
 1244    compiler_warnings(T, Clause, Options).
 1245
 1246compiler_warning(eq_vv(A,B), _Clause, Options) -->
 1247    (   { A == B }
 1248    ->  [ 'Test is always true: ~W'-[A==B, Options] ]
 1249    ;   [ 'Test is always false: ~W'-[A==B, Options] ]
 1250    ).
 1251compiler_warning(eq_singleton(A,B), _Clause, Options) -->
 1252    [ 'Test is always false: ~W'-[A==B, Options] ].
 1253compiler_warning(neq_vv(A,B), _Clause, Options) -->
 1254    (   { A \== B }
 1255    ->  [ 'Test is always true: ~W'-[A\==B, Options] ]
 1256    ;   [ 'Test is always false: ~W'-[A\==B, Options] ]
 1257    ).
 1258compiler_warning(neq_singleton(A,B), _Clause, Options) -->
 1259    [ 'Test is always true: ~W'-[A\==B, Options] ].
 1260compiler_warning(unify_singleton(A,B), _Clause, Options) -->
 1261    [ 'Unified variable is not used: ~W'-[A=B, Options] ].
 1262compiler_warning(always(Bool, Pred, Arg), _Clause, Options) -->
 1263    { Goal =.. [Pred,Arg] },
 1264    [ 'Test is always ~w: ~W'-[Bool, Goal, Options] ].
 1265compiler_warning(unbalanced_var(V), _Clause, Options) -->
 1266    [ 'Variable not introduced in all branches: ~W'-[V, Options] ].
 1267compiler_warning(branch_singleton(V), _Clause, Options) -->
 1268    [ 'Singleton variable in branch: ~W'-[V, Options] ].
 1269compiler_warning(negation_singleton(V), _Clause, Options) -->
 1270    [ 'Singleton variable in \\+: ~W'-[V, Options] ].
 1271compiler_warning(multiton(V), _Clause, Options) -->
 1272    [ 'Singleton-marked variable appears more than once: ~W'-[V, Options] ].
 1273
 1274print_goal_options(
 1275    [ quoted(true),
 1276      portray(true)
 1277    ]).
 1278
 1279
 1280                 /*******************************
 1281                 *      TOPLEVEL MESSAGES       *
 1282                 *******************************/
 1283
 1284prolog_message(version) -->
 1285    { current_prolog_flag(version_git, Version) },
 1286    !,
 1287    [ '~w'-[Version] ].
 1288prolog_message(version) -->
 1289    { current_prolog_flag(version_data, swi(Major,Minor,Patch,Options))
 1290    },
 1291    (   { memberchk(tag(Tag), Options) }
 1292    ->  [ '~w.~w.~w-~w'-[Major, Minor, Patch, Tag] ]
 1293    ;   [ '~w.~w.~w'-[Major, Minor, Patch] ]
 1294    ).
 1295prolog_message(address_bits) -->
 1296    { current_prolog_flag(address_bits, Bits)
 1297    },
 1298    !,
 1299    [ '~d bits, '-[Bits] ].
 1300prolog_message(threads) -->
 1301    { current_prolog_flag(threads, true)
 1302    },
 1303    !,
 1304    [ 'threaded, ' ].
 1305prolog_message(threads) -->
 1306    [].
 1307prolog_message(copyright) -->
 1308    [ 'SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.', nl,
 1309      'Please run ', ansi(code, '?- license.', []), ' for legal details.'
 1310    ].
 1311prolog_message(documentaton) -->
 1312    [ 'For online help and background, visit ', url('https://www.swi-prolog.org') ],
 1313    (   { exists_source(library(help)) }
 1314    ->  [ nl,
 1315          'For built-in help, use ', ansi(code, '?- help(Topic).', []),
 1316          ' or ', ansi(code, '?- apropos(Word).', [])
 1317        ]
 1318    ;   []
 1319    ).
 1320prolog_message(about) -->
 1321    [ 'SWI-Prolog version (' ],
 1322    prolog_message(threads),
 1323    prolog_message(address_bits),
 1324    ['version ' ],
 1325    prolog_message(version),
 1326    [ ')', nl ],
 1327    prolog_message(copyright).
 1328prolog_message(halt) -->
 1329    [ 'halt' ].
 1330prolog_message(break(begin, Level)) -->
 1331    [ 'Break level ~d'-[Level] ].
 1332prolog_message(break(end, Level)) -->
 1333    [ 'Exit break level ~d'-[Level] ].
 1334prolog_message(var_query(_)) -->
 1335    [ '... 1,000,000 ............ 10,000,000 years later', nl, nl,
 1336      '~t~8|>> 42 << (last release gives the question)'
 1337    ].
 1338prolog_message(close_on_abort(Stream)) -->
 1339    [ 'Abort: closed stream ~p'-[Stream] ].
 1340prolog_message(cancel_halt(Reason)) -->
 1341    [ 'Halt cancelled: ~p'-[Reason] ].
 1342prolog_message(on_error(halt(Status))) -->
 1343    { statistics(errors, Errors),
 1344      statistics(warnings, Warnings)
 1345    },
 1346    [ 'Halting with status ~w due to ~D errors and ~D warnings'-
 1347      [Status, Errors, Warnings] ].
 1348
 1349prolog_message(query(QueryResult)) -->
 1350    query_result(QueryResult).
 1351
 1352query_result(no) -->            % failure
 1353    [ ansi(truth(false), 'false.', []) ],
 1354    extra_line.
 1355query_result(yes(true, [])) -->      % prompt_alternatives_on: groundness
 1356    !,
 1357    [ ansi(truth(true), 'true.', []) ],
 1358    extra_line.
 1359query_result(yes(Delays, Residuals)) -->
 1360    result([], Delays, Residuals),
 1361    extra_line.
 1362query_result(done) -->          % user typed <CR>
 1363    extra_line.
 1364query_result(yes(Bindings, Delays, Residuals)) -->
 1365    result(Bindings, Delays, Residuals),
 1366    prompt(yes, Bindings, Delays, Residuals).
 1367query_result(more(Bindings, Delays, Residuals)) -->
 1368    result(Bindings, Delays, Residuals),
 1369    prompt(more, Bindings, Delays, Residuals).
 1370:- if(current_prolog_flag(emscripten, true)). 1371query_result(help) -->
 1372    [ ansi(bold, '  Possible actions:', []), nl,
 1373      '  ; (n,r,space): redo              | t:       trace&redo'-[], nl,
 1374      '  *:             show choicepoint  | . (c,a): stop'-[], nl,
 1375      '  w:             write             | p:       print'-[], nl,
 1376      '  +:             max_depth*5       | -:       max_depth//5'-[], nl,
 1377      '  h (?):         help'-[],
 1378      nl, nl
 1379    ].
 1380:- else. 1381query_result(help) -->
 1382    [ ansi(bold, '  Possible actions:', []), nl,
 1383      '  ; (n,r,space,TAB): redo              | t:           trace&redo'-[], nl,
 1384      '  *:                 show choicepoint  | . (c,a,RET): stop'-[], nl,
 1385      '  w:                 write             | p:           print'-[], nl,
 1386      '  +:                 max_depth*5       | -:           max_depth//5'-[], nl,
 1387      '  b:                 break             | h (?):       help'-[],
 1388      nl, nl
 1389    ].
 1390:- endif. 1391query_result(action) -->
 1392    [ 'Action? '-[], flush ].
 1393query_result(confirm) -->
 1394    [ 'Please answer \'y\' or \'n\'? '-[], flush ].
 1395query_result(eof) -->
 1396    [ nl ].
 1397query_result(toplevel_open_line) -->
 1398    [].
 1399
 1400prompt(Answer, [], true, []-[]) -->
 1401    !,
 1402    prompt(Answer, empty).
 1403prompt(Answer, _, _, _) -->
 1404    !,
 1405    prompt(Answer, non_empty).
 1406
 1407prompt(yes, empty) -->
 1408    !,
 1409    [ ansi(truth(true), 'true.', []) ],
 1410    extra_line.
 1411prompt(yes, _) -->
 1412    !,
 1413    [ full_stop ],
 1414    extra_line.
 1415prompt(more, empty) -->
 1416    !,
 1417    [ ansi(truth(true), 'true ', []), flush ].
 1418prompt(more, _) -->
 1419    !,
 1420    [ ' '-[], flush ].
 1421
 1422result(Bindings, Delays, Residuals) -->
 1423    { current_prolog_flag(answer_write_options, Options0),
 1424      Options = [partial(true)|Options0],
 1425      GOptions = [priority(999)|Options0]
 1426    },
 1427    wfs_residual_program(Delays, GOptions),
 1428    bindings(Bindings, [priority(699)|Options]),
 1429    (   {Residuals == []-[]}
 1430    ->  bind_delays_sep(Bindings, Delays),
 1431        delays(Delays, GOptions)
 1432    ;   bind_res_sep(Bindings, Residuals),
 1433        residuals(Residuals, GOptions),
 1434        (   {Delays == true}
 1435        ->  []
 1436        ;   [','-[], nl],
 1437            delays(Delays, GOptions)
 1438        )
 1439    ).
 1440
 1441bindings([], _) -->
 1442    [].
 1443bindings([binding(Names,Skel,Subst)|T], Options) -->
 1444    { '$last'(Names, Name) },
 1445    var_names(Names), value(Name, Skel, Subst, Options),
 1446    (   { T \== [] }
 1447    ->  [ ','-[], nl ],
 1448        bindings(T, Options)
 1449    ;   []
 1450    ).
 1451
 1452var_names([Name]) -->
 1453    !,
 1454    [ '~w = '-[Name] ].
 1455var_names([Name1,Name2|T]) -->
 1456    !,
 1457    [ '~w = ~w, '-[Name1, Name2] ],
 1458    var_names([Name2|T]).
 1459
 1460
 1461value(Name, Skel, Subst, Options) -->
 1462    (   { var(Skel), Subst = [Skel=S] }
 1463    ->  { Skel = '$VAR'(Name) },
 1464        [ '~W'-[S, Options] ]
 1465    ;   [ '~W'-[Skel, Options] ],
 1466        substitution(Subst, Options)
 1467    ).
 1468
 1469substitution([], _) --> !.
 1470substitution([N=V|T], Options) -->
 1471    [ ', ', ansi(comment, '% where', []), nl,
 1472      '    ~w = ~W'-[N,V,Options] ],
 1473    substitutions(T, Options).
 1474
 1475substitutions([], _) --> [].
 1476substitutions([N=V|T], Options) -->
 1477    [ ','-[], nl, '    ~w = ~W'-[N,V,Options] ],
 1478    substitutions(T, Options).
 1479
 1480
 1481residuals(Normal-Hidden, Options) -->
 1482    residuals1(Normal, Options),
 1483    bind_res_sep(Normal, Hidden),
 1484    (   {Hidden == []}
 1485    ->  []
 1486    ;   [ansi(comment, '% with pending residual goals', []), nl]
 1487    ),
 1488    residuals1(Hidden, Options).
 1489
 1490residuals1([], _) -->
 1491    [].
 1492residuals1([G|Gs], Options) -->
 1493    (   { Gs \== [] }
 1494    ->  [ '~W,'-[G, Options], nl ],
 1495        residuals1(Gs, Options)
 1496    ;   [ '~W'-[G, Options] ]
 1497    ).
 1498
 1499wfs_residual_program(true, _Options) -->
 1500    !.
 1501wfs_residual_program(Goal, _Options) -->
 1502    { current_prolog_flag(toplevel_list_wfs_residual_program, true),
 1503      '$current_typein_module'(TypeIn),
 1504      (   current_predicate(delays_residual_program/2)
 1505      ->  true
 1506      ;   use_module(library(wfs), [delays_residual_program/2])
 1507      ),
 1508      delays_residual_program(TypeIn:Goal, TypeIn:Program),
 1509      Program \== []
 1510    },
 1511    !,
 1512    [ ansi(comment, '% WFS residual program', []), nl ],
 1513    [ ansi(wfs(residual_program), '~@', ['$messages':list_clauses(Program)]) ].
 1514wfs_residual_program(_, _) --> [].
 1515
 1516delays(true, _Options) -->
 1517    !.
 1518delays(Goal, Options) -->
 1519    { current_prolog_flag(toplevel_list_wfs_residual_program, true)
 1520    },
 1521    !,
 1522    [ ansi(truth(undefined), '~W', [Goal, Options]) ].
 1523delays(_, _Options) -->
 1524    [ ansi(truth(undefined), undefined, []) ].
 1525
 1526:- public list_clauses/1. 1527
 1528list_clauses([]).
 1529list_clauses([H|T]) :-
 1530    (   system_undefined(H)
 1531    ->  true
 1532    ;   portray_clause(user_output, H, [indent(4)])
 1533    ),
 1534    list_clauses(T).
 1535
 1536system_undefined((undefined :- tnot(undefined))).
 1537system_undefined((answer_count_restraint :- tnot(answer_count_restraint))).
 1538system_undefined((radial_restraint :- tnot(radial_restraint))).
 1539
 1540bind_res_sep(_, []) --> !.
 1541bind_res_sep(_, []-[]) --> !.
 1542bind_res_sep([], _) --> !.
 1543bind_res_sep(_, _) --> [','-[], nl].
 1544
 1545bind_delays_sep([], _) --> !.
 1546bind_delays_sep(_, true) --> !.
 1547bind_delays_sep(_, _) --> [','-[], nl].
 1548
 1549extra_line -->
 1550    { current_prolog_flag(toplevel_extra_white_line, true) },
 1551    !,
 1552    ['~N'-[]].
 1553extra_line -->
 1554    [].
 1555
 1556prolog_message(if_tty(Message)) -->
 1557    (   {current_prolog_flag(tty_control, true)}
 1558    ->  [ at_same_line ], list(Message)
 1559    ;   []
 1560    ).
 1561prolog_message(halt(Reason)) -->
 1562    [ '~w: halt'-[Reason] ].
 1563prolog_message(no_action(Char)) -->
 1564    [ 'Unknown action: ~c (h for help)'-[Char], nl ].
 1565
 1566prolog_message(history(help(Show, Help))) -->
 1567    [ 'History Commands:', nl,
 1568      '    !!.              Repeat last query', nl,
 1569      '    !nr.             Repeat query numbered <nr>', nl,
 1570      '    !str.            Repeat last query starting with <str>', nl,
 1571      '    !?str.           Repeat last query holding <str>', nl,
 1572      '    ^old^new.        Substitute <old> into <new> of last query', nl,
 1573      '    !nr^old^new.     Substitute in query numbered <nr>', nl,
 1574      '    !str^old^new.    Substitute in query starting with <str>', nl,
 1575      '    !?str^old^new.   Substitute in query holding <str>', nl,
 1576      '    ~w.~21|Show history list'-[Show], nl,
 1577      '    ~w.~21|Show this list'-[Help], nl, nl
 1578    ].
 1579prolog_message(history(no_event)) -->
 1580    [ '! No such event' ].
 1581prolog_message(history(bad_substitution)) -->
 1582    [ '! Bad substitution' ].
 1583prolog_message(history(expanded(Event))) -->
 1584    [ '~w.'-[Event] ].
 1585prolog_message(history(history(Events))) -->
 1586    history_events(Events).
 1587prolog_message(history(no_history)) -->
 1588    [ '! event history not supported in this version' ].
 1589
 1590history_events([]) -->
 1591    [].
 1592history_events([Nr-Event|T]) -->
 1593    [ ansi(comment, '%', []),
 1594      ansi(bold, '~t~w ~6|', [Nr]),
 1595      ansi(code, '~s', [Event]),
 1596      nl
 1597    ],
 1598    history_events(T).
 user_version_messages(+Terms)//
Helper for the welcome message to print information registered using version/1.
 1606user_version_messages([]) --> [].
 1607user_version_messages([H|T]) -->
 1608    user_version_message(H),
 1609    user_version_messages(T).
 user_version_message(+Term)
 1613user_version_message(Term) -->
 1614    translate_message(Term), !, [nl].
 1615user_version_message(Atom) -->
 1616    [ '~w'-[Atom], nl ].
 1617
 1618
 1619                 /*******************************
 1620                 *       DEBUGGER MESSAGES      *
 1621                 *******************************/
 1622
 1623prolog_message(spy(Head)) -->
 1624    [ 'New spy point on ' ],
 1625    goal_predicate(Head).
 1626prolog_message(already_spying(Head)) -->
 1627    [ 'Already spying ' ],
 1628    goal_predicate(Head).
 1629prolog_message(nospy(Head)) -->
 1630    [ 'Removed spy point from ' ],
 1631    goal_predicate(Head).
 1632prolog_message(trace_mode(OnOff)) -->
 1633    [ 'Trace mode switched to ~w'-[OnOff] ].
 1634prolog_message(debug_mode(OnOff)) -->
 1635    [ 'Debug mode switched to ~w'-[OnOff] ].
 1636prolog_message(debugging(OnOff, Threads)) -->
 1637    [ 'Debug mode is ~w'-[OnOff] ],
 1638    debugging_threads(Threads).
 1639prolog_message(spying([])) -->
 1640    !,
 1641    [ 'No spy points' ].
 1642prolog_message(spying(Heads)) -->
 1643    [ 'Spy points (see spy/1) on:', nl ],
 1644    predicate_list(Heads).
 1645prolog_message(trace(Head, [])) -->
 1646    !,
 1647    [ '    ' ], goal_predicate(Head), [ ' Not tracing'-[], nl].
 1648prolog_message(trace(Head, Ports)) -->
 1649    { '$member'(Port, Ports), compound(Port),
 1650      !,
 1651      numbervars(Head+Ports, 0, _, [singletons(true)])
 1652    },
 1653    [ '    ~p: ~p'-[Head,Ports] ].
 1654prolog_message(trace(Head, Ports)) -->
 1655    [ '    ' ], goal_predicate(Head), [ ': ~w'-[Ports], nl].
 1656prolog_message(tracing([])) -->
 1657    !,
 1658    [ 'No traced predicates (see trace/1,2)' ].
 1659prolog_message(tracing(Heads)) -->
 1660    [ 'Trace points (see trace/1,2) on:', nl ],
 1661    tracing_list(Heads).
 1662
 1663goal_predicate(Head) -->
 1664    { predicate_property(Head, file(File)),
 1665      predicate_property(Head, line_count(Line)),
 1666      goal_to_predicate_indicator(Head, PI),
 1667      term_string(PI, PIS, [quoted(true)])
 1668    },
 1669    [ url(File:Line, PIS) ].
 1670goal_predicate(Head) -->
 1671    { goal_to_predicate_indicator(Head, PI)
 1672    },
 1673    [ ansi(code, '~p', [PI]) ].
 1674
 1675
 1676predicate_list([]) -->                  % TBD: Share with dwim, etc.
 1677    [].
 1678predicate_list([H|T]) -->
 1679    [ '    ' ], goal_predicate(H), [nl],
 1680    predicate_list(T).
 1681
 1682tracing_list([]) -->
 1683    [].
 1684tracing_list([trace(Head, Ports)|T]) -->
 1685    translate_message(trace(Head, Ports)),
 1686    tracing_list(T).
 1687
 1688debugging_threads([]) -->
 1689    [].
 1690debugging_threads(ThreadsByClass) -->
 1691    [ nl, 'Threads in the following classes run in debug mode:', nl],
 1692    list_threads_by_class(ThreadsByClass).
 1693
 1694list_threads_by_class([]) -->
 1695    [].
 1696list_threads_by_class([H|T]) -->
 1697    list_thread_class(H),
 1698    list_threads_by_class(T).
 1699
 1700list_thread_class(Class-Threads) -->
 1701    { length(Threads, Count) },
 1702    [ '    Class ', ansi(code, '~p', [Class]), ': ~D threads'-[Count] ].
 1703
 1704% frame(+Frame, +Choice, +Port, +PC) - Print for the debugger.
 1705prolog_message(frame(Frame, _Choice, backtrace, _PC)) -->
 1706    !,
 1707    { prolog_frame_attribute(Frame, level, Level)
 1708    },
 1709    [ ansi(frame(level), '~t[~D] ~10|', [Level]) ],
 1710    frame_context(Frame),
 1711    frame_goal(Frame).
 1712prolog_message(frame(Frame, _Choice, choice, PC)) -->
 1713    !,
 1714    prolog_message(frame(Frame, backtrace, PC)).
 1715prolog_message(frame(_, _Choice, cut_call(_PC), _)) --> !.
 1716prolog_message(frame(Frame, _Choice, Port, _PC)) -->
 1717    frame_flags(Frame),
 1718    port(Port),
 1719    frame_level(Frame),
 1720    frame_context(Frame),
 1721    frame_depth_limit(Port, Frame),
 1722    frame_goal(Frame),
 1723    [ flush ].
 1724
 1725% frame(:Goal, +Trace)		- Print for trace/2
 1726prolog_message(frame(Goal, trace(Port))) -->
 1727    !,
 1728    thread_context,
 1729    [ ' T ' ],
 1730    port(Port),
 1731    goal(Goal).
 1732prolog_message(frame(Goal, trace(Port, Id))) -->
 1733    !,
 1734    thread_context,
 1735    [ ' T ' ],
 1736    port(Port, Id),
 1737    goal(Goal).
 1738
 1739frame_goal(Frame) -->
 1740    { prolog_frame_attribute(Frame, goal, Goal)
 1741    },
 1742    goal(Goal).
 1743
 1744goal(Goal0) -->
 1745    { clean_goal(Goal0, Goal),
 1746      current_prolog_flag(debugger_write_options, Options)
 1747    },
 1748    [ '~W'-[Goal, Options] ].
 1749
 1750frame_level(Frame) -->
 1751    { prolog_frame_attribute(Frame, level, Level)
 1752    },
 1753    [ '(~D) '-[Level] ].
 1754
 1755frame_context(Frame) -->
 1756    (   { current_prolog_flag(debugger_show_context, true),
 1757          prolog_frame_attribute(Frame, context_module, Context)
 1758        }
 1759    ->  [ '[~w] '-[Context] ]
 1760    ;   []
 1761    ).
 1762
 1763frame_depth_limit(fail, Frame) -->
 1764    { prolog_frame_attribute(Frame, depth_limit_exceeded, true)
 1765    },
 1766    !,
 1767    [ '[depth-limit exceeded] ' ].
 1768frame_depth_limit(_, _) -->
 1769    [].
 1770
 1771frame_flags(Frame) -->
 1772    { prolog_frame_attribute(Frame, goal, Goal),
 1773      (   predicate_property(Goal, transparent)
 1774      ->  T = '^'
 1775      ;   T = ' '
 1776      ),
 1777      (   predicate_property(Goal, spying)
 1778      ->  S = '*'
 1779      ;   S = ' '
 1780      )
 1781    },
 1782    [ '~w~w '-[T, S] ].
 1783
 1784% trace/1 context handling
 1785port(Port, Dict) -->
 1786    { _{level:Level, start:Time} :< Dict
 1787    },
 1788    (   { Port \== call,
 1789          get_time(Now),
 1790          Passed is (Now - Time)*1000.0
 1791        }
 1792    ->  [ '[~d +~1fms] '-[Level, Passed] ]
 1793    ;   [ '[~d] '-[Level] ]
 1794    ),
 1795    port(Port).
 1796port(Port, _Id-Level) -->
 1797    [ '[~d] '-[Level] ],
 1798    port(Port).
 1799
 1800port(PortTerm) -->
 1801    { functor(PortTerm, Port, _),
 1802      port_name(Port, Name)
 1803    },
 1804    !,
 1805    [ ansi(port(Port), '~w: ', [Name]) ].
 1806
 1807port_name(call,      'Call').
 1808port_name(exit,      'Exit').
 1809port_name(fail,      'Fail').
 1810port_name(redo,      'Redo').
 1811port_name(unify,     'Unify').
 1812port_name(exception, 'Exception').
 1813
 1814clean_goal(M:Goal, Goal) :-
 1815    hidden_module(M),
 1816    !.
 1817clean_goal(M:Goal, Goal) :-
 1818    predicate_property(M:Goal, built_in),
 1819    !.
 1820clean_goal(Goal, Goal).
 1821
 1822
 1823                 /*******************************
 1824                 *        COMPATIBILITY         *
 1825                 *******************************/
 1826
 1827prolog_message(compatibility(renamed(Old, New))) -->
 1828    [ 'The predicate ~p has been renamed to ~p.'-[Old, New], nl,
 1829      'Please update your sources for compatibility with future versions.'
 1830    ].
 1831
 1832
 1833                 /*******************************
 1834                 *            THREADS           *
 1835                 *******************************/
 1836
 1837prolog_message(abnormal_thread_completion(Goal, exception(Ex))) -->
 1838    !,
 1839    [ 'Thread running "~p" died on exception: '-[Goal] ],
 1840    translate_message(Ex).
 1841prolog_message(abnormal_thread_completion(Goal, fail)) -->
 1842    [ 'Thread running "~p" died due to failure'-[Goal] ].
 1843prolog_message(threads_not_died(Running)) -->
 1844    [ 'The following threads wouldn\'t die: ~p'-[Running] ].
 1845
 1846
 1847                 /*******************************
 1848                 *             PACKS            *
 1849                 *******************************/
 1850
 1851prolog_message(pack(attached(Pack, BaseDir))) -->
 1852    [ 'Attached package ~w at ~q'-[Pack, BaseDir] ].
 1853prolog_message(pack(duplicate(Entry, OldDir, Dir))) -->
 1854    [ 'Package ~w already attached at ~q.'-[Entry,OldDir], nl,
 1855      '\tIgnoring version from ~q'- [Dir]
 1856    ].
 1857prolog_message(pack(no_arch(Entry, Arch))) -->
 1858    [ 'Package ~w: no binary for architecture ~w'-[Entry, Arch] ].
 1859
 1860                 /*******************************
 1861                 *             MISC             *
 1862                 *******************************/
 1863
 1864prolog_message(null_byte_in_path(Component)) -->
 1865    [ '0-byte in PATH component: ~p (skipped directory)'-[Component] ].
 1866prolog_message(invalid_tmp_dir(Dir, Reason)) -->
 1867    [ 'Cannot use ~p as temporary file directory: ~w'-[Dir, Reason] ].
 1868prolog_message(ambiguous_stream_pair(Pair)) -->
 1869    [ 'Ambiguous operation on stream pair ~p'-[Pair] ].
 1870prolog_message(backcomp(init_file_moved(FoundFile))) -->
 1871    { absolute_file_name(app_config('init.pl'), InitFile,
 1872                         [ file_errors(fail)
 1873                         ])
 1874    },
 1875    [ 'The location of the config file has moved'-[], nl,
 1876      '  from "~w"'-[FoundFile], nl,
 1877      '  to   "~w"'-[InitFile], nl,
 1878      '  See https://www.swi-prolog.org/modified/config-files.html'-[]
 1879    ].
 1880prolog_message(not_accessed_flags(List)) -->
 1881    [ 'The following Prolog flags have been set but not used:', nl ],
 1882    flags(List).
 1883prolog_message(prolog_flag_invalid_preset(Flag, Preset, _Type, New)) -->
 1884    [ 'Prolog flag ', ansi(code, '~q', Flag), ' has been (re-)created with a type that is \c
 1885       incompatible with its value.', nl,
 1886      'Value updated from ', ansi(code, '~p', [Preset]), ' to default (',
 1887      ansi(code, '~p', [New]), ')'
 1888    ].
 1889
 1890
 1891flags([H|T]) -->
 1892    ['  ', ansi(code, '~q', [H])],
 1893    (   {T == []}
 1894    ->  []
 1895    ;   [nl],
 1896        flags(T)
 1897    ).
 1898
 1899
 1900		 /*******************************
 1901		 *          DEPRECATED		*
 1902		 *******************************/
 1903
 1904deprecated(set_prolog_stack(_Stack,limit)) -->
 1905    [ 'set_prolog_stack/2: limit(Size) sets the combined limit.'-[], nl,
 1906      'See https://www.swi-prolog.org/changes/stack-limit.html'
 1907    ].
 1908deprecated(autoload(TargetModule, File, _M:PI, expansion)) -->
 1909    !,
 1910    [ 'Auto-loading ', ansi(code, '~p', [PI]), ' from ' ],
 1911    load_file(File), [ ' into ' ],
 1912    target_module(TargetModule),
 1913    [ ' is deprecated due to term- or goal-expansion' ].
 1914deprecated(source_search_working_directory(File, _FullFile)) -->
 1915    [ 'Found file ', ansi(code, '~w', [File]),
 1916      ' relative to the current working directory.', nl,
 1917      'This behaviour is deprecated but still supported by', nl,
 1918      'the Prolog flag ',
 1919      ansi(code, source_search_working_directory, []), '.', nl
 1920    ].
 1921deprecated(moved_library(Old, New)) -->
 1922    [ 'Library was moved: ~q --> ~q'-[Old, New] ].
 1923
 1924load_file(File) -->
 1925    { file_base_name(File, Base),
 1926      absolute_file_name(library(Base), File, [access(read), file_errors(fail)]),
 1927      file_name_extension(Clean, pl, Base)
 1928    },
 1929    !,
 1930    [ ansi(code, '~p', [library(Clean)]) ].
 1931load_file(File) -->
 1932    [ url(File) ].
 1933
 1934target_module(Module) -->
 1935    { module_property(Module, file(File)) },
 1936    !,
 1937    load_file(File).
 1938target_module(Module) -->
 1939    [ 'module ', ansi(code, '~p', [Module]) ].
 1940
 1941
 1942
 1943		 /*******************************
 1944		 *           TRIPWIRES		*
 1945		 *******************************/
 1946
 1947tripwire_message(max_integer_size, Bytes) -->
 1948    !,
 1949    [ 'Trapped tripwire max_integer_size: big integers and \c
 1950       rationals are limited to ~D bytes'-[Bytes] ].
 1951tripwire_message(Wire, Context) -->
 1952    [ 'Trapped tripwire ~w for '-[Wire] ],
 1953    tripwire_context(Wire, Context).
 1954
 1955tripwire_context(_, ATrie) -->
 1956    { '$is_answer_trie'(ATrie, _),
 1957      !,
 1958      '$tabling':atrie_goal(ATrie, QGoal),
 1959      user_predicate_indicator(QGoal, Goal)
 1960    },
 1961    [ '~p'-[Goal] ].
 1962tripwire_context(_, Ctx) -->
 1963    [ '~p'-[Ctx] ].
 1964
 1965
 1966		 /*******************************
 1967		 *     INTERNATIONALIZATION	*
 1968		 *******************************/
 1969
 1970:- create_prolog_flag(message_language, default, []).
 message_lang(-Lang) is multi
True when Lang is a language id preferred for messages. Starts with the most specific language (e.g., nl_BE) and ends with en.
 1977message_lang(Lang) :-
 1978    current_message_lang(Lang0),
 1979    (   Lang0 == en
 1980    ->  Lang = en
 1981    ;   sub_atom(Lang0, 0, _, _, en_)
 1982    ->  longest_id(Lang0, Lang)
 1983    ;   (   longest_id(Lang0, Lang)
 1984        ;   Lang = en
 1985        )
 1986    ).
 1987
 1988longest_id(Lang, Id) :-
 1989    split_string(Lang, "_-", "", [H|Components]),
 1990    longest_prefix(Components, Taken),
 1991    atomic_list_concat([H|Taken], '_', Id).
 1992
 1993longest_prefix([H|T0], [H|T]) :-
 1994    longest_prefix(T0, T).
 1995longest_prefix(_, []).
 current_message_lang(-Lang) is det
Get the current language for messages.
 2001current_message_lang(Lang) :-
 2002    (   current_prolog_flag(message_language, Lang0),
 2003        Lang0 \== default
 2004    ->  Lang = Lang0
 2005    ;   os_user_lang(Lang0)
 2006    ->  clean_encoding(Lang0, Lang1),
 2007        set_prolog_flag(message_language, Lang1),
 2008        Lang = Lang1
 2009    ;   Lang = en
 2010    ).
 2011
 2012os_user_lang(Lang) :-
 2013    current_prolog_flag(windows, true),
 2014    win_get_user_preferred_ui_languages(name, [Lang|_]).
 2015os_user_lang(Lang) :-
 2016    catch(setlocale(messages, _, ''), _, fail),
 2017    setlocale(messages, Lang, Lang).
 2018os_user_lang(Lang) :-
 2019    getenv('LANG', Lang).
 2020
 2021
 2022clean_encoding(Lang0, Lang) :-
 2023    (   sub_atom(Lang0, A, _, _, '.')
 2024    ->  sub_atom(Lang0, 0, A, _, Lang)
 2025    ;   Lang = Lang0
 2026    ).
 2027
 2028		 /*******************************
 2029		 *          PRIMITIVES		*
 2030		 *******************************/
 2031
 2032code(Term) -->
 2033    code('~p', Term).
 2034
 2035code(Format, Term) -->
 2036    [ ansi(code, Format, [Term]) ].
 2037
 2038list([]) --> [].
 2039list([H|T]) --> [H], list(T).
 2040
 2041
 2042		 /*******************************
 2043		 *        DEFAULT THEME		*
 2044		 *******************************/
 2045
 2046:- public default_theme/2. 2047
 2048default_theme(var,                    [fg(red)]).
 2049default_theme(code,                   [fg(blue)]).
 2050default_theme(comment,                [fg(green)]).
 2051default_theme(warning,                [fg(red)]).
 2052default_theme(error,                  [bold, fg(red)]).
 2053default_theme(truth(false),           [bold, fg(red)]).
 2054default_theme(truth(true),            [bold]).
 2055default_theme(truth(undefined),       [bold, fg(cyan)]).
 2056default_theme(wfs(residual_program),  [fg(cyan)]).
 2057default_theme(frame(level),           [bold]).
 2058default_theme(port(call),             [bold, fg(green)]).
 2059default_theme(port(exit),             [bold, fg(green)]).
 2060default_theme(port(fail),             [bold, fg(red)]).
 2061default_theme(port(redo),             [bold, fg(yellow)]).
 2062default_theme(port(unify),            [bold, fg(blue)]).
 2063default_theme(port(exception),        [bold, fg(magenta)]).
 2064default_theme(message(informational), [fg(green)]).
 2065default_theme(message(information),   [fg(green)]).
 2066default_theme(message(debug(_)),      [fg(blue)]).
 2067default_theme(message(Level),         Attrs) :-
 2068    nonvar(Level),
 2069    default_theme(Level, Attrs).
 2070
 2071
 2072                 /*******************************
 2073                 *      PRINTING MESSAGES       *
 2074                 *******************************/
 2075
 2076:- multifile
 2077    user:message_hook/3,
 2078    prolog:message_prefix_hook/2. 2079:- dynamic
 2080    user:message_hook/3,
 2081    prolog:message_prefix_hook/2. 2082:- thread_local
 2083    user:thread_message_hook/3. 2084:- '$notransact'((user:message_hook/3,
 2085                  prolog:message_prefix_hook/2,
 2086                  user:thread_message_hook/3)).
 print_message(+Kind, +Term)
Print an error message using a term as generated by the exception system.
 2093print_message(Level, _Term) :-
 2094    msg_property(Level, stream(S)),
 2095    stream_property(S, error(true)),
 2096    !.
 2097print_message(Level, Term) :-
 2098    setup_call_cleanup(
 2099        notrace(push_msg(Term, Stack)),
 2100        ignore(print_message_guarded(Level, Term)),
 2101        notrace(pop_msg(Stack))),
 2102    !.
 2103print_message(Level, Term) :-
 2104    (   Level \== silent
 2105    ->  format(user_error, 'Recursive ~w message: ~q~n', [Level, Term]),
 2106        autoload_call(backtrace(20))
 2107    ;   true
 2108    ).
 2109
 2110push_msg(Term, Messages) :-
 2111    nb_current('$inprint_message', Messages),
 2112    !,
 2113    \+ ( '$member'(Msg, Messages),
 2114         Msg =@= Term
 2115       ),
 2116    Stack = [Term|Messages],
 2117    b_setval('$inprint_message', Stack).
 2118push_msg(Term, []) :-
 2119    b_setval('$inprint_message', [Term]).
 2120
 2121pop_msg(Stack) :-
 2122    nb_delete('$inprint_message'),              % delete history
 2123    b_setval('$inprint_message', Stack).
 2124
 2125print_message_guarded(Level, Term) :-
 2126    (   must_print(Level, Term)
 2127    ->  (   prolog:message_action(Term, Level),
 2128            fail                                % forall/2 is cleaner, but not yet
 2129        ;   true                                % defined
 2130        ),
 2131        (   translate_message(Term, Lines, [])
 2132        ->  (   nonvar(Term),
 2133                (   notrace(user:thread_message_hook(Term, Level, Lines))
 2134                ->  true
 2135                ;   notrace(user:message_hook(Term, Level, Lines))
 2136                )
 2137            ->  true
 2138            ;   '$inc_message_count'(Level),
 2139                print_system_message(Term, Level, Lines),
 2140                maybe_halt_on_error(Level)
 2141            )
 2142        )
 2143    ;   true
 2144    ).
 2145
 2146maybe_halt_on_error(error) :-
 2147    current_prolog_flag(on_error, halt),
 2148    !,
 2149    halt(1).
 2150maybe_halt_on_error(warning) :-
 2151    current_prolog_flag(on_warning, halt),
 2152    !,
 2153    halt(1).
 2154maybe_halt_on_error(_).
 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.
 2164print_system_message(_, silent, _) :- !.
 2165print_system_message(_, informational, _) :-
 2166    current_prolog_flag(verbose, silent),
 2167    !.
 2168print_system_message(_, banner, _) :-
 2169    current_prolog_flag(verbose, silent),
 2170    !.
 2171print_system_message(_, _, []) :- !.
 2172print_system_message(Term, Kind, Lines) :-
 2173    catch(flush_output(user_output), _, true),      % may not exist
 2174    source_location(File, Line),
 2175    Term \= error(syntax_error(_), _),
 2176    msg_property(Kind, location_prefix(File:Line, LocPrefix, LinePrefix)),
 2177    !,
 2178    to_list(LocPrefix, LocPrefixL),
 2179    insert_prefix(Lines, LinePrefix, Ctx, PrefixLines),
 2180    '$append'([ [begin(Kind, Ctx)],
 2181                LocPrefixL,
 2182                [nl],
 2183                PrefixLines,
 2184                [end(Ctx)]
 2185              ],
 2186              AllLines),
 2187    msg_property(Kind, stream(Stream)),
 2188    ignore(stream_property(Stream, position(Pos))),
 2189    print_message_lines(Stream, AllLines),
 2190    (   \+ stream_property(Stream, position(Pos)),
 2191        msg_property(Kind, wait(Wait)),
 2192        Wait > 0
 2193    ->  sleep(Wait)
 2194    ;   true
 2195    ).
 2196print_system_message(_, Kind, Lines) :-
 2197    msg_property(Kind, stream(Stream)),
 2198    print_message_lines(Stream, kind(Kind), Lines).
 2199
 2200to_list(ListIn, List) :-
 2201    is_list(ListIn),
 2202    !,
 2203    List = ListIn.
 2204to_list(NonList, [NonList]).
 2205
 2206:- multifile
 2207    user:message_property/2. 2208
 2209msg_property(Kind, Property) :-
 2210    notrace(user:message_property(Kind, Property)),
 2211    !.
 2212msg_property(Kind, prefix(Prefix)) :-
 2213    msg_prefix(Kind, Prefix),
 2214    !.
 2215msg_property(_, prefix('~N')) :- !.
 2216msg_property(query, stream(user_output)) :- !.
 2217msg_property(_, stream(user_error)) :- !.
 2218msg_property(error, tag('ERROR')).
 2219msg_property(warning, tag('Warning')).
 2220msg_property(Level,
 2221             location_prefix(File:Line,
 2222                             ['~N~w: '-[Tag], url(File:Line), ':'],
 2223                             '~N~w:    '-[Tag])) :-
 2224    include_msg_location(Level),
 2225    msg_property(Level, tag(Tag)).
 2226msg_property(error,   wait(0.1)) :- !.
 2227
 2228include_msg_location(warning).
 2229include_msg_location(error).
 2230
 2231msg_prefix(debug(_), Prefix) :-
 2232    msg_context('~N% ', Prefix).
 2233msg_prefix(Level, Prefix) :-
 2234    msg_property(Level, tag(Tag)),
 2235    atomics_to_string(['~N', Tag, ': '], Prefix0),
 2236    msg_context(Prefix0, Prefix).
 2237msg_prefix(informational, '~N% ').
 2238msg_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.

 2252msg_context(Prefix0, Prefix) :-
 2253    current_prolog_flag(message_context, Context),
 2254    is_list(Context),
 2255    !,
 2256    add_message_context(Context, Prefix0, Prefix).
 2257msg_context(Prefix, Prefix).
 2258
 2259add_message_context([], Prefix, Prefix).
 2260add_message_context([H|T], Prefix0, Prefix) :-
 2261    (   add_message_context1(H, Prefix0, Prefix1)
 2262    ->  true
 2263    ;   Prefix1 = Prefix0
 2264    ),
 2265    add_message_context(T, Prefix1, Prefix).
 2266
 2267add_message_context1(Context, Prefix0, Prefix) :-
 2268    prolog:message_prefix_hook(Context, Extra),
 2269    atomics_to_string([Prefix0, Extra, ' '], Prefix).
 2270add_message_context1(time, Prefix0, Prefix) :-
 2271    get_time(Now),
 2272    format_time(string(S), '%T.%3f ', Now),
 2273    string_concat(Prefix0, S, Prefix).
 2274add_message_context1(time(Format), Prefix0, Prefix) :-
 2275    get_time(Now),
 2276    format_time(string(S), Format, Now),
 2277    atomics_to_string([Prefix0, S, ' '], Prefix).
 2278add_message_context1(thread, Prefix0, Prefix) :-
 2279    \+ current_prolog_flag(toplevel_thread, true),
 2280    thread_self(Id0),
 2281    !,
 2282    (   atom(Id0)
 2283    ->  Id = Id0
 2284    ;   thread_property(Id0, id(Id))
 2285    ),
 2286    format(string(Prefix), '~w[Thread ~w] ', [Prefix0, Id]).
 print_message_lines(+Stream, +PrefixOrKind, +Lines)
Quintus compatibility predicate to print message lines using a prefix.
 2293print_message_lines(Stream, kind(Kind), Lines) :-
 2294    !,
 2295    msg_property(Kind, prefix(Prefix)),
 2296    insert_prefix(Lines, Prefix, Ctx, PrefixLines),
 2297    '$append'([ begin(Kind, Ctx)
 2298              | PrefixLines
 2299              ],
 2300              [ end(Ctx)
 2301              ],
 2302              AllLines),
 2303    print_message_lines(Stream, AllLines).
 2304print_message_lines(Stream, Prefix, Lines) :-
 2305    insert_prefix(Lines, Prefix, _, PrefixLines),
 2306    print_message_lines(Stream, PrefixLines).
 insert_prefix(+Lines, +Prefix, +Ctx, -PrefixedLines)
 2310insert_prefix([at_same_line|Lines0], Prefix, Ctx, Lines) :-
 2311    !,
 2312    prefix_nl(Lines0, Prefix, Ctx, Lines).
 2313insert_prefix(Lines0, Prefix, Ctx, [prefix(Prefix)|Lines]) :-
 2314    prefix_nl(Lines0, Prefix, Ctx, Lines).
 2315
 2316prefix_nl([], _, _, [nl]).
 2317prefix_nl([nl], _, _, [nl]) :- !.
 2318prefix_nl([flush], _, _, [flush]) :- !.
 2319prefix_nl([nl|T0], Prefix, Ctx, [nl, prefix(Prefix)|T]) :-
 2320    !,
 2321    prefix_nl(T0, Prefix, Ctx, T).
 2322prefix_nl([ansi(Attrs,Fmt,Args)|T0], Prefix, Ctx,
 2323          [ansi(Attrs,Fmt,Args,Ctx)|T]) :-
 2324    !,
 2325    prefix_nl(T0, Prefix, Ctx, T).
 2326prefix_nl([H|T0], Prefix, Ctx, [H|T]) :-
 2327    prefix_nl(T0, Prefix, Ctx, T).
 print_message_lines(+Stream, +Lines)
 2331print_message_lines(Stream, Lines) :-
 2332    with_output_to(
 2333        Stream,
 2334        notrace(print_message_lines_guarded(current_output, Lines))).
 2335
 2336print_message_lines_guarded(_, []) :- !.
 2337print_message_lines_guarded(S, [H|T]) :-
 2338    line_element(S, H),
 2339    print_message_lines_guarded(S, T).
 2340
 2341line_element(S, E) :-
 2342    prolog:message_line_element(S, E),
 2343    !.
 2344line_element(S, full_stop) :-
 2345    !,
 2346    '$put_token'(S, '.').           % insert space if needed.
 2347line_element(S, nl) :-
 2348    !,
 2349    nl(S).
 2350line_element(S, prefix(Fmt-Args)) :-
 2351    !,
 2352    safe_format(S, Fmt, Args).
 2353line_element(S, prefix(Fmt)) :-
 2354    !,
 2355    safe_format(S, Fmt, []).
 2356line_element(S, flush) :-
 2357    !,
 2358    flush_output(S).
 2359line_element(S, Fmt-Args) :-
 2360    !,
 2361    safe_format(S, Fmt, Args).
 2362line_element(S, ansi(_, Fmt, Args)) :-
 2363    !,
 2364    safe_format(S, Fmt, Args).
 2365line_element(S, ansi(_, Fmt, Args, _Ctx)) :-
 2366    !,
 2367    safe_format(S, Fmt, Args).
 2368line_element(S, url(URL)) :-
 2369    !,
 2370    print_link(S, URL).
 2371line_element(S, url(_URL, Fmt-Args)) :-
 2372    !,
 2373    safe_format(S, Fmt, Args).
 2374line_element(S, url(_URL, Fmt)) :-
 2375    !,
 2376    safe_format(S, Fmt, []).
 2377line_element(_, begin(_Level, _Ctx)) :- !.
 2378line_element(_, end(_Ctx)) :- !.
 2379line_element(S, Fmt) :-
 2380    safe_format(S, Fmt, []).
 2381
 2382print_link(S, File:Line:Column) :-
 2383    !,
 2384    safe_format(S, '~w:~d:~d', [File, Line, Column]).
 2385print_link(S, File:Line) :-
 2386    !,
 2387    safe_format(S, '~w:~d', [File, Line]).
 2388print_link(S, File) :-
 2389    safe_format(S, '~w', [File]).
 safe_format(+Stream, +Format, +Args) is det
 2393safe_format(S, Fmt, Args) :-
 2394    E = error(_,_),
 2395    catch(format(S,Fmt,Args), E,
 2396          format_failed(S,Fmt,Args,E)).
 2397
 2398format_failed(S, _Fmt, _Args, E) :-
 2399    stream_property(S, error(true)),
 2400    !,
 2401    throw(E).
 2402format_failed(S, Fmt, Args, error(E,_)) :-
 2403    format(S, '~N    [[ EXCEPTION while printing message ~q~n\c
 2404                        ~7|with arguments ~W:~n\c
 2405                        ~7|raised: ~W~n~4|]]~n',
 2406           [ Fmt,
 2407             Args, [quoted(true), max_depth(10)],
 2408             E, [quoted(true), max_depth(10)]
 2409           ]).
 message_to_string(+Term, -String)
Translate an error term into a string
 2415message_to_string(Term, Str) :-
 2416    translate_message(Term, Actions, []),
 2417    !,
 2418    actions_to_format(Actions, Fmt, Args),
 2419    format(string(Str), Fmt, Args).
 2420
 2421actions_to_format([], '', []) :- !.
 2422actions_to_format([nl], '', []) :- !.
 2423actions_to_format([Term, nl], Fmt, Args) :-
 2424    !,
 2425    actions_to_format([Term], Fmt, Args).
 2426actions_to_format([nl|T], Fmt, Args) :-
 2427    !,
 2428    actions_to_format(T, Fmt0, Args),
 2429    atom_concat('~n', Fmt0, Fmt).
 2430actions_to_format([ansi(_Attrs, Fmt0, Args0)|Tail], Fmt, Args) :-
 2431    !,
 2432    actions_to_format(Tail, Fmt1, Args1),
 2433    atom_concat(Fmt0, Fmt1, Fmt),
 2434    append_args(Args0, Args1, Args).
 2435actions_to_format([url(Pos)|Tail], Fmt, Args) :-
 2436    !,
 2437    actions_to_format(Tail, Fmt1, Args1),
 2438    url_actions_to_format(url(Pos), Fmt1, Args1, Fmt, Args).
 2439actions_to_format([url(URL, Label)|Tail], Fmt, Args) :-
 2440    !,
 2441    actions_to_format(Tail, Fmt1, Args1),
 2442    url_actions_to_format(url(URL, Label), Fmt1, Args1, Fmt, Args).
 2443actions_to_format([Fmt0-Args0|Tail], Fmt, Args) :-
 2444    !,
 2445    actions_to_format(Tail, Fmt1, Args1),
 2446    atom_concat(Fmt0, Fmt1, Fmt),
 2447    append_args(Args0, Args1, Args).
 2448actions_to_format([Skip|T], Fmt, Args) :-
 2449    action_skip(Skip),
 2450    !,
 2451    actions_to_format(T, Fmt, Args).
 2452actions_to_format([Term|Tail], Fmt, Args) :-
 2453    atomic(Term),
 2454    !,
 2455    actions_to_format(Tail, Fmt1, Args),
 2456    atom_concat(Term, Fmt1, Fmt).
 2457actions_to_format([Term|Tail], Fmt, Args) :-
 2458    actions_to_format(Tail, Fmt1, Args1),
 2459    atom_concat('~w', Fmt1, Fmt),
 2460    append_args([Term], Args1, Args).
 2461
 2462action_skip(at_same_line).
 2463action_skip(flush).
 2464action_skip(begin(_Level, _Ctx)).
 2465action_skip(end(_Ctx)).
 2466
 2467url_actions_to_format(url(File:Line:Column), Fmt1, Args1, Fmt, Args) :-
 2468    !,
 2469    atom_concat('~w:~d:~d', Fmt1, Fmt),
 2470    append_args([File,Line,Column], Args1, Args).
 2471url_actions_to_format(url(File:Line), Fmt1, Args1, Fmt, Args) :-
 2472    !,
 2473    atom_concat('~w:~d', Fmt1, Fmt),
 2474    append_args([File,Line], Args1, Args).
 2475url_actions_to_format(url(File), Fmt1, Args1, Fmt, Args) :-
 2476    !,
 2477    atom_concat('~w', Fmt1, Fmt),
 2478    append_args([File], Args1, Args).
 2479url_actions_to_format(url(_URL, Label), Fmt1, Args1, Fmt, Args) :-
 2480    !,
 2481    atom_concat('~w', Fmt1, Fmt),
 2482    append_args([Label], Args1, Args).
 2483
 2484
 2485append_args(M:Args0, Args1, M:Args) :-
 2486    !,
 2487    strip_module(Args1, _, A1),
 2488    to_list(Args0, Args01),
 2489    '$append'(Args01, A1, Args).
 2490append_args(Args0, Args1, Args) :-
 2491    strip_module(Args1, _, A1),
 2492    to_list(Args0, Args01),
 2493    '$append'(Args01, A1, Args).
 2494
 2495                 /*******************************
 2496                 *    MESSAGES TO PRINT ONCE    *
 2497                 *******************************/
 2498
 2499:- dynamic
 2500    printed/2.
 print_once(Message, Level)
True for messages that must be printed only once.
 2506print_once(compatibility(_), _).
 2507print_once(null_byte_in_path(_), _).
 2508print_once(deprecated(_), _).
 must_print(+Level, +Message)
True if the message must be printed.
 2514must_print(Level, Message) :-
 2515    nonvar(Message),
 2516    print_once(Message, Level),
 2517    !,
 2518    \+ printed(Message, Level),
 2519    assert(printed(Message, Level)).
 2520must_print(_, _)