+bool msg_location_is_empty (const struct msg_location *);
+void msg_location_format (const struct msg_location *, struct string *);
+
+struct msg_stack
+ {
+ struct msg_location *location;
+ char *description;
+ };
+
+void msg_stack_destroy (struct msg_stack *);
+struct msg_stack *msg_stack_dup (const struct msg_stack *);
+
+/* A message. */
+struct msg
+ {
+ enum msg_category category; /* Message category. */
+ enum msg_severity severity; /* Message severity. */
+ struct msg_location *location; /* Code location. */
+ struct msg_stack **stack;
+ size_t n_stack;
+ char *command_name; /* Name of erroneous command, or NULL. */
+ char *text; /* Error text. */
+ };
+
+/* Initialization. */
+struct msg_handler
+ {
+ void (*output_msg) (const struct msg *, void *aux);
+ void *aux;
+
+ void (*lex_source_ref) (const struct lex_source *);
+ void (*lex_source_unref) (struct lex_source *);
+ struct substring (*lex_source_get_line) (const struct lex_source *,
+ int line);
+ };
+void msg_set_handler (const struct msg_handler *);
+
+/* Working with messages. */
+struct msg *msg_dup (const struct msg *);
+void msg_destroy(struct msg *);
+char *msg_to_string (const struct msg *);
+
+/* Emitting messages. */
+void vmsg (enum msg_class, const struct msg_location *,
+ const char *format, va_list args)
+ PRINTF_FORMAT (3, 0);
+void msg (enum msg_class, const char *format, ...)