+parse_msg (struct dfm_reader *reader, const struct substring *token,
+ char *text, enum msg_severity severity)
+{
+ int first_column = 0;
+ if (token)
+ {
+ struct substring line = dfm_get_record (reader);
+ if (token->string >= line.string && token->string < ss_end (line))
+ first_column = ss_pointer_to_position (line, token->string) + 1;
+ }
+
+ int line_number = dfm_get_line_number (reader);
+ struct msg_location *location = xmalloc (sizeof *location);
+ int last_column = (first_column && token->length
+ ? first_column + token->length - 1
+ : 0);
+ *location = (struct msg_location) {
+ .file_name = intern_new (dfm_get_file_name (reader)),
+ .start = { .line = line_number, .column = first_column },
+ .end = { .line = line_number, .column = last_column },
+ };
+ struct msg *m = xmalloc (sizeof *m);
+ *m = (struct msg) {
+ .category = MSG_C_DATA,
+ .severity = severity,
+ .location = location,
+ .text = text,
+ };
+ msg_emit (m);
+}
+
+static void PRINTF_FORMAT (3, 4)
+parse_warning (struct dfm_reader *reader, const struct substring *token,
+ const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ parse_msg (reader, token, xvasprintf (format, args), MSG_S_WARNING);
+ va_end (args);
+}
+
+static void PRINTF_FORMAT (3, 4)
+parse_error (struct dfm_reader *reader, const struct substring *token,
+ const char *format, ...)