return (use == FMT_FOR_INPUT
? xasprintf (ngettext (
"Input format %s specifies %d decimal place, "
- "but the given width allows at most "
- "%d decimals.",
+ "but width %d allows at most %d decimals.",
"Input format %s specifies %d decimal places, "
- "but the given width allows at most "
- "%d decimals.",
+ "but width %d allows at most %d decimals.",
spec->d),
- str, spec->d, max_d)
+ str, spec->d, spec->w, max_d)
: xasprintf (ngettext (
"Output format %s specifies %d decimal place, "
- "but the given width allows at most "
- "%d decimals.",
+ "but width %d allows at most %d decimals.",
"Output format %s specifies %d decimal places, "
- "but the given width allows at most "
- "%d decimals.",
+ "but width %d allows at most %d decimals.",
spec->d),
- str, spec->d, max_d));
+ str, spec->d, spec->w, max_d));
else
return (use == FMT_FOR_INPUT
? xasprintf (ngettext (
"Input format %s specifies %d decimal place, "
- "but the given width does not allow "
- "for any decimals.",
+ "but width %d does not allow for any decimals.",
"Input format %s specifies %d decimal places, "
- "but the given width does not allow "
- "for any decimals.",
+ "but width %d does not allow for any decimals.",
spec->d),
- str, spec->d)
+ str, spec->d, spec->w)
: xasprintf (ngettext (
"Output format %s specifies %d decimal place, "
- "but the given width does not allow "
- "for any decimals.",
+ "but width %d does not allow for any decimals.",
"Output format %s specifies %d decimal places, "
- "but the given width does not allow "
- "for any decimals.",
+ "but width %d does not allow for any decimals.",
spec->d),
- str, spec->d));
+ str, spec->d, spec->w));
}
return NULL;
}
+char *
+fmt_check_input__ (const struct fmt_spec *spec)
+{
+ return fmt_check__ (spec, FMT_FOR_INPUT);
+}
+
+char *
+fmt_check_output__ (const struct fmt_spec *spec)
+{
+ return fmt_check__ (spec, FMT_FOR_OUTPUT);
+}
+
static bool
-fmt_emit_and_free_error (char *error)
+error_to_bool (char *error)
{
if (error)
{
- msg (SE, "%s", error);
free (error);
return false;
}
return true;
}
-/* Checks whether SPEC is valid for USE and returns nonzero if so. Otherwise,
- emits an error message for the current source location and returns zero. */
+/* Returns true if SPEC is valid for USE, false otherwise. */
bool
fmt_check (const struct fmt_spec *spec, enum fmt_use use)
{
- return fmt_emit_and_free_error (fmt_check__ (spec, use));
+ return error_to_bool (fmt_check__ (spec, use));
}
-/* Checks whether SPEC is valid as an input format and returns
- nonzero if so. Otherwise, emits an error message and returns
- zero. */
+/* Returns true if SPEC is valid as an input format, otherwise false. */
bool
fmt_check_input (const struct fmt_spec *spec)
{
return fmt_check (spec, FMT_FOR_INPUT);
}
-/* Checks whether SPEC is valid as an output format and returns
- true if so. Otherwise, emits an error message and returns false. */
+/* Returnst true SPEC is valid as an output format, false otherwise. */
bool
fmt_check_output (const struct fmt_spec *spec)
{
/* Checks that FORMAT is appropriate for a variable of the given VAR_TYPE and
returns NULL if so. Otherwise returns a malloc()'d error message that the
- calelr must eventually free(). */
+ caller must eventually free(). VARNAME is optional and only used in the
+ error message.*/
char *
-fmt_check_type_compat__ (const struct fmt_spec *format, enum val_type var_type)
+fmt_check_type_compat__ (const struct fmt_spec *format, const char *varname,
+ enum val_type var_type)
{
assert (val_type_is_valid (var_type));
if ((var_type == VAL_STRING) != (fmt_is_string (format->type) != 0))
{
char str[FMT_STRING_LEN_MAX + 1];
- return xasprintf (_("%s variables are not compatible with %s format %s."),
- var_type == VAL_STRING ? _("String") : _("Numeric"),
- var_type == VAL_STRING ? _("numeric") : _("string"),
- fmt_to_string (format, str));
+ fmt_to_string (format, str);
+ if (var_type == VAL_STRING)
+ {
+ if (varname)
+ return xasprintf (_("String variable %s is not compatible with "
+ "numeric format %s."), varname, str);
+ else
+ return xasprintf (_("String variables are not compatible with "
+ "numeric format %s."), str);
+ }
+ else
+ {
+ if (varname)
+ return xasprintf (_("Numeric variable %s is not compatible with "
+ "string format %s."), varname, str);
+ else
+ return xasprintf (_("Numeric variables are not compatible with "
+ "string format %s."), str);
+ }
}
return NULL;
}
-/* Checks that FORMAT is appropriate for a variable of the given
- VAR_TYPE and returns true if so. Otherwise returns false and
- emits an error message. */
+/* Returns FORMAT is appropriate for a variable of the given VAR_TYPE and
+ returns true if so, otherwise false. */
bool
fmt_check_type_compat (const struct fmt_spec *format, enum val_type var_type)
{
- return fmt_emit_and_free_error (fmt_check_type_compat__ (format, var_type));
+ return error_to_bool (fmt_check_type_compat__ (format, NULL, var_type));
}
/* Checks that FORMAT is appropriate for a variable of the given WIDTH and
returns NULL if so. Otherwise returns a malloc()'d error message that the
- calelr must eventually free(). */
+ caller must eventually free(). VARNAME is optional and only used in the
+ error message. */
char *
-fmt_check_width_compat__ (const struct fmt_spec *format, int width)
+fmt_check_width_compat__ (const struct fmt_spec *format, const char *varname,
+ int width)
{
- char *error = fmt_check_type_compat__ (format, val_type_from_width (width));
+ char *error = fmt_check_type_compat__ (format, varname,
+ val_type_from_width (width));
if (error)
return error;
if (fmt_var_width (format) != width)
{
- char str[FMT_STRING_LEN_MAX + 1];
- return xasprintf (_("String variable with width %d is not compatible "
- "with format %s."),
- width, fmt_to_string (format, str));
+ char format_str[FMT_STRING_LEN_MAX + 1];
+ fmt_to_string (format, format_str);
+
+ char better_str[FMT_STRING_LEN_MAX + 1];
+ if (format->type == FMT_A)
+ snprintf (better_str, sizeof better_str, "A%d", width);
+ else
+ snprintf (better_str, sizeof better_str, "AHEX%d", width * 2);
+
+ if (varname)
+ return xasprintf (_("String variable %s with width %d is not "
+ "compatible with format %s. "
+ "Use format %s instead."),
+ varname, width, format_str, better_str);
+ else
+ return xasprintf (_("String variable with width %d is not compatible "
+ "with format %s. Use format %s instead."),
+ width, format_str, better_str);
}
return NULL;
}
-/* Checks that FORMAT is appropriate for a variable of the given
- WIDTH and returns true if so. Otherwise returns false and
- emits an error message. */
+/* Checks that FORMAT is appropriate for a variable of the given WIDTH and
+ returns true if so, otherwise false. */
bool
fmt_check_width_compat (const struct fmt_spec *format, int width)
{
- return fmt_emit_and_free_error (fmt_check_width_compat__ (format, width));
+ return error_to_bool (fmt_check_width_compat__ (format, NULL, width));
}
/* Returns the width corresponding to FORMAT. The return value
uint8_t w = u32 >> 8;
uint8_t d = u32;
- msg_disable ();
- f->w = w;
- f->d = d;
- bool ok = fmt_from_io (raw_type, &f->type);
- if (ok)
- {
- if (loose)
- fmt_fix_output (f);
- else
- ok = fmt_check_output (f);
- }
- if (ok)
- ok = fmt_check_width_compat (f, width);
- msg_enable ();
+ enum fmt_type type;
+ if (!fmt_from_io (raw_type, &type))
+ return false;
+
+ *f = (struct fmt_spec) { .type = type, .w = w, .d = d };
+
+ if (loose)
+ fmt_fix_output (f);
+ else if (!fmt_check_output (f))
+ return false;
- return ok;
+ return fmt_check_width_compat (f, width);
}
/* Returns true if TYPE may be used as an input format,