struct matrix_var *variable;
struct read_file *eof;
};
+
+ struct msg_location *location;
};
static void
case MOP_EOF:
break;
}
+ msg_location_destroy (e->location);
free (e);
}
.subs = xmemdup (subs, n_subs * sizeof *subs),
.n_subs = n_subs
};
+
+ for (size_t i = 0; i < n_subs; i++)
+ msg_location_merge (&e->location, subs[i]->location);
return e;
}
if (!f)
return false;
- lex_get_n (s->lexer, 2);
-
struct matrix_expr *e = xmalloc (sizeof *e);
- *e = (struct matrix_expr) { .op = f->op, .subs = NULL };
+ *e = (struct matrix_expr) {
+ .op = f->op,
+ .location = lex_get_location (s->lexer, 0, 0)
+ };
+ lex_get_n (s->lexer, 2);
if (lex_token (s->lexer) != T_RPAREN)
{
size_t allocated_subs = 0;
do
{
+ struct msg_location *arg_location = lex_get_location (s->lexer, 0, 0);
struct matrix_expr *sub = matrix_parse_expr (s);
if (!sub)
- goto error;
+ {
+ msg_location_destroy (arg_location);
+ goto error;
+ }
+ if (!sub->location)
+ {
+ lex_extend_location (s->lexer, 0, arg_location);
+ sub->location = arg_location;
+ }
+ else
+ msg_location_destroy (arg_location);
if (e->n_subs >= allocated_subs)
e->subs = x2nrealloc (e->subs, &allocated_subs, sizeof *e->subs);
struct matrix_lvalue
{
struct matrix_var *var;
+ struct msg_location *var_location;
struct matrix_expr *indexes[2];
size_t n_indexes;
};
struct matrix_lvalue *lvalue = xzalloc (sizeof *lvalue);
if (!lex_force_id (s->lexer))
goto error;
+ lvalue->var_location = lex_get_location (s->lexer, 0, 0);
lvalue->var = matrix_var_lookup (s, lex_tokss (s->lexer));
if (lex_next_token (s->lexer, 1) == T_LPAREN)
{
gsl_matrix *dm = lvalue->var->value;
if (!dm)
{
- msg (SE, _("Undefined variable %s."), lvalue->var->name);
+ msg_at (SE, lvalue->var_location,
+ _("Undefined variable %s."), lvalue->var->name);
return false;
}
else if (dm->size1 == 0 || dm->size2 == 0)
{
- msg (SE, _("Cannot index %zu×%zu matrix."),
- dm->size1, dm->size2);
+ msg_at (SE, lvalue->var_location,
+ _("Cannot index %zu×%zu matrix."), dm->size1, dm->size2);
return false;
}
else if (lvalue->n_indexes == 1)
{
if (!is_vector (dm))
{
- msg (SE, _("Can't use vector indexing on %zu×%zu matrix %s."),
- dm->size1, dm->size2, lvalue->var->name);
+ msg_at (SE, lvalue->var_location,
+ _("Can't use vector indexing on %zu×%zu matrix %s."),
+ dm->size1, dm->size2, lvalue->var->name);
return false;
}
return matrix_lvalue_evaluate_vector (lvalue->indexes[0],
void
-vmsg (enum msg_class class, const char *format, va_list args)
+vmsg (enum msg_class class, const struct msg_location *location,
+ const char *format, va_list args)
{
struct msg *m = xmalloc (sizeof *m);
*m = (struct msg) {
.category = msg_class_to_category (class),
.severity = msg_class_to_severity (class),
+ .location = msg_location_dup (location),
.text = xvasprintf (format, args),
};
msg_emit (m);
{
va_list args;
va_start (args, format);
- vmsg (class, format, args);
+ vmsg (class, NULL, format, args);
va_end (args);
}
-
+/* Outputs error message in CLASS, with text FORMAT, formatted with printf.
+ LOCATION is the reported location for the message. */
+void
+msg_at (enum msg_class class, const struct msg_location *location,
+ const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ vmsg (class, location, format, args);
+ va_end (args);
+}
void
msg_error (int errnum, const char *format, ...)
void msg_location_destroy (struct msg_location *);
struct msg_location *msg_location_dup (const struct msg_location *);
+void msg_location_merge (struct msg_location **, const struct msg_location *);
+
bool msg_location_is_empty (const struct msg_location *);
void msg_location_format (const struct msg_location *, struct string *);
char *msg_to_string (const struct msg *);
/* Emitting messages. */
-void vmsg (enum msg_class class, const char *format, va_list args)
- PRINTF_FORMAT (2, 0);
+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, ...)
PRINTF_FORMAT (2, 3);
+void msg_at (enum msg_class, const struct msg_location *,
+ const char *format, ...)
+ PRINTF_FORMAT (3, 4);
void msg_emit (struct msg *);
void msg_error (int errnum, const char *format, ...)