Node:Message Processing, Next:, Previous:Messages and Queries, Up:Messages and Queries



Message Processing

Every message issued by the Prolog system is displayed using a single predicate:

print_message(+Severity, +Message)

Message is a term that encodes the message to be printed. The format of message terms is subject to change, but can be inspected in the file library('SU_messages') of the SICStus Prolog distribution.

The atom Severity specifies the type (or importance) of the message. The following table lists the severities known to the SICStus Prolog system, together with the line prefixes used in displaying messages of the given severity:

error '! ' for error messages
warning '* ' for warning messages
informational '% ' for informational messages
help '' for help messages
query '' for query texts (see Query Processing)
silent '' a special kind of message which normally does not produce any outpu, but can be intercepted by hooks

print_message/2 is a built-in predicate, so that users can invoke it to have their own messages processed in the same way as the system messages.

The processing and printing of the messages is highly customizable. For example, this allows the user to change the language of the messages, or to make them appear in dialog windows rather than on the terminal.

Phases of Message Processing

Messages are processed in two major phases. The user can influence the behavior of each phase using appropriate hooks, described later.

The first phase is called the message generation phase: it determines the text of the message from the input (the abstract message term). No printing is done here. In this phase the user can change the phrasing or the language of the messages.

The result of the first phase is created in the form of a format-command list. This is a list whose elements are format-commands, or the atom nl denoting the end of a line. A format-command describes a piece of text not extending over a line boundary and it can be one of the following:

FormatString-Args
format(FormatString, Args)
This indicates that the message text should appear as if printed by
format(FormatString, Args).

write_term(Term, Options)
This indicates that the message text should appear as if printed by
write_term(Term, Options).

write_term(Term)
Equivalent to write_term(Term, Options) where Options is the actual value of the prolog flag toplevel_print_options.

As an example, let us see what happens in case of the toplevel call _ =:= 3. An instantiation error is raised by the Prolog system, which is caught, and the abstract message term instantiation_error(_=:=3,1) is generated (assuming sicstus execution mode)--the first argument is the goal, and the second argument is the position of the uninstantiated variable within the goal. In the first phase of message processing this is converted to the following format-command list:

['Instantiation error'-[],' in argument ~d of ~q'-[1,=:= /2],nl,
 'goal:  '-[],write_term(_=:=3),nl]

A minor transformation, so-called line splitting is performed on the message text before it is handed over to the second phase. The format-command list is broken up along the nl atoms into a list of lines, where each line is a list of format-commands. We will use the term format-command lines to refer to the result of this transformation.

In the example above, the result of this conversion is the following:

[['Instantiation error'-[],' in argument ~d of ~q'-[1,=:= /2]],
 ['goal:  '-[],write_term(_=:=3)]]
The above format-command lines term is the input of the second phase of message processing.

The second phase is called the message printing phase, this is where the message is actually displayed. The severity of the message is used here to prefix each line of the message with some characters indicating the type of the message, as listed above.

The user can change the exact method of printing (e.g. redirection of messages to a stream, a window, or using different prefixes, etc.) through appropriate hooks.

In our example the following lines are printed by the second phase of processing:

! Instantiation error in argument 1 of =:= /2
! goal:  _=:=3

The user can override the default message processing mechanism in the following two ways:

Message Generation Phase

The default message generation predicates are located in the library('SU_messages') file, in the 'SU_messages' module, together with other message and query related predicates. This is advantageous when these predicates have to be changed as a whole (for example when translating all messages to another language), because this can be done simply by replacing the file library('SU_messages') by a new one.

In the message generation phase three alternative methods are tried:

The hook predicate generate_message_hook/3 can be used to override the default behavior, or to handle new messages defined by the programmer, which do not fit the default message generation schemes. The latter can also be achieved by adding new clauses to the extendible 'SU_messages':generate_message/3 predicate.

If both the hook and the default method refuses to handle the message, then the following simple format-command list is generated from the abstract message term Message:

['~q'-[Message],nl]
This will result in displaying the abstract message term itself, as if printed by writeq/1.

For messages of the severity silent the message generation phase is skipped, and the [] format-command list is returned as the output.

Message Printing Phase

By default this phase is handled by the built-in predicate print_message_lines/3. Each line of the message is prefixed with a string depending on the severity, and is printed to user_error. The query severity is special--no newline is printed after the last line of the message.

This behavior can be overridden by defining the hook predicate message_hook/3, which is called with the severity of the message, the abstract message term and its translation to format-command lines. It can be used to make smaller changes, for example by calling print_message_lines/3 with a stream argument other than user_error, or to implement a totally different display method such as using dialog windows for messages.

For messages of the severity silent the message printing phase consists of calling the hook predicate message_hook/3 only. Even if the hook fails, no printing is done.