fmt_for_input (enum fmt_type type, int w, int d)
{
struct fmt_spec f = { .type = type, .w = w, .d = d };
- assert (fmt_check_input (&f));
+ assert (fmt_check_input (f));
return f;
}
fmt_for_output (enum fmt_type type, int w, int d)
{
struct fmt_spec f = { .type = type, .w = w, .d = d };
- assert (fmt_check_output (&f));
+ assert (fmt_check_output (f));
return f;
}
/* Returns the output format specifier corresponding to input
format specifier INPUT. */
struct fmt_spec
-fmt_for_output_from_input (const struct fmt_spec *input,
+fmt_for_output_from_input (struct fmt_spec input,
const struct fmt_settings *settings)
{
struct fmt_spec output;
assert (fmt_check_input (input));
- output.type = fmt_input_to_output (input->type);
- output.w = input->w;
+ output.type = fmt_input_to_output (input.type);
+ output.w = input.w;
if (output.w > fmt_max_output_width (output.type))
output.w = fmt_max_output_width (output.type);
else if (output.w < fmt_min_output_width (output.type))
output.w = fmt_min_output_width (output.type);
- output.d = input->d;
+ output.d = input.d;
- switch (input->type)
+ switch (input.type)
{
case FMT_Z:
output.w++;
case FMT_PCT:
{
const struct fmt_number_style *style =
- fmt_settings_get_style (settings, input->type);
+ fmt_settings_get_style (settings, input.type);
output.w += fmt_affix_width (style);
- if (style->grouping != 0 && input->w - input->d >= 3)
- output.w += (input->w - input->d - 1) / 3;
+ if (style->grouping != 0 && input.w - input.d >= 3)
+ output.w += (input.w - input.d - 1) / 3;
if (output.d > 0)
output.w++;
}
break;
case FMT_E:
- output.d = MAX (input->d, 3);
- output.w = MAX (input->w, output.d + 7);
+ output.d = MAX (input.d, 3);
+ output.w = MAX (input.w, output.d + 7);
break;
case FMT_PIBHEX:
- output.w = max_digits_for_bytes (input->w / 2) + 1;
+ output.w = max_digits_for_bytes (input.w / 2) + 1;
break;
case FMT_RB:
case FMT_P:
case FMT_PK:
- output.w = 2 * input->w + (input->d > 0);
+ output.w = 2 * input.w + (input.d > 0);
break;
case FMT_IB:
case FMT_PIB:
- output.w = max_digits_for_bytes (input->w) + 1;
+ output.w = max_digits_for_bytes (input.w) + 1;
if (output.d > 0)
output.w++;
break;
break;
case FMT_AHEX:
- output.w = input->w / 2;
+ output.w = input.w / 2;
break;
case FMT_DATE:
break;
case FMT_MTIME:
- if (input->d)
- output.w = MAX (input->w, input->d + 6);
+ if (input.d)
+ output.w = MAX (input.w, input.d + 6);
break;
case FMT_YMDHMS:
- if (input->w)
- output.w = MAX (input->w, input->d + 20);
+ if (input.w)
+ output.w = MAX (input.w, input.d + 20);
break;
default:
if (output.w > fmt_max_output_width (output.type))
output.w = fmt_max_output_width (output.type);
- assert (fmt_check_output (&output));
+ assert (fmt_check_output (output));
return output;
}
returns a malloc()'d string that describes the error. The caller must
eventually free() the string. */
char *
-fmt_check__ (const struct fmt_spec *spec, enum fmt_use use)
+fmt_check__ (struct fmt_spec spec, enum fmt_use use)
{
char str[FMT_STRING_LEN_MAX + 1];
int min_w, max_w, max_d;
- assert (is_fmt_type (spec->type));
+ assert (is_fmt_type (spec.type));
fmt_to_string (spec, str);
- if (use == FMT_FOR_INPUT && !fmt_usable_for_input (spec->type))
+ if (use == FMT_FOR_INPUT && !fmt_usable_for_input (spec.type))
return xasprintf (_("Format %s may not be used for input."), str);
- if (spec->w % fmt_step_width (spec->type))
+ if (spec.w % fmt_step_width (spec.type))
{
- assert (fmt_step_width (spec->type) == 2);
+ assert (fmt_step_width (spec.type) == 2);
return (use == FMT_FOR_INPUT
? xasprintf (_("Input format %s specifies width %d, "
"but %s requires an even width."),
- str, spec->w, fmt_name (spec->type))
+ str, spec.w, fmt_name (spec.type))
: xasprintf (_("Output format %s specifies width %d, "
"but %s requires an even width."),
- str, spec->w, fmt_name (spec->type)));
+ str, spec.w, fmt_name (spec.type)));
}
- min_w = fmt_min_width (spec->type, use);
- max_w = fmt_max_width (spec->type, use);
- if (spec->w < min_w || spec->w > max_w)
+ min_w = fmt_min_width (spec.type, use);
+ max_w = fmt_max_width (spec.type, use);
+ if (spec.w < min_w || spec.w > max_w)
return (use == FMT_FOR_INPUT
? xasprintf (_("Input format %s specifies width %d, but "
"%s requires a width between %d and %d."),
- str, spec->w, fmt_name (spec->type), min_w, max_w)
+ str, spec.w, fmt_name (spec.type), min_w, max_w)
: xasprintf (_("Output format %s specifies width %d, but "
"%s requires a width between %d and %d."),
- str, spec->w, fmt_name (spec->type), min_w, max_w));
+ str, spec.w, fmt_name (spec.type), min_w, max_w));
- max_d = fmt_max_decimals (spec->type, spec->w, use);
- if (!fmt_takes_decimals (spec->type) && spec->d != 0)
+ max_d = fmt_max_decimals (spec.type, spec.w, use);
+ if (!fmt_takes_decimals (spec.type) && spec.d != 0)
return (use == FMT_FOR_INPUT
? xasprintf (ngettext (
"Input format %s specifies %d decimal "
"Input format %s specifies %d decimal "
"places, but %s does not allow any "
"decimals.",
- spec->d),
- str, spec->d, fmt_name (spec->type))
+ spec.d),
+ str, spec.d, fmt_name (spec.type))
: xasprintf (ngettext (
"Output format %s specifies %d decimal "
"place, but %s does not allow any decimals.",
"Output format %s specifies %d decimal places, but "
"%s does not allow any decimals.",
- spec->d),
- str, spec->d, fmt_name (spec->type)));
- else if (spec->d > max_d)
+ spec.d),
+ str, spec.d, fmt_name (spec.type)));
+ else if (spec.d > max_d)
{
if (max_d > 0)
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.",
- spec->d),
- str, spec->d, max_d)
+ "but width %d allows at most %d decimals.",
+ spec.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.",
- spec->d),
- str, spec->d, max_d));
+ "but width %d allows at most %d decimals.",
+ spec.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.",
- spec->d),
- str, spec->d)
+ "but width %d does not allow for any decimals.",
+ 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.",
- spec->d),
- str, spec->d));
+ "but width %d does not allow for any decimals.",
+ spec.d),
+ str, spec.d, spec.w));
}
return NULL;
}
+char *
+fmt_check_input__ (struct fmt_spec spec)
+{
+ return fmt_check__ (spec, FMT_FOR_INPUT);
+}
+
+char *
+fmt_check_output__ (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)
+fmt_check (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)
+fmt_check_input (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)
+fmt_check_output (struct fmt_spec spec)
{
return fmt_check (spec, FMT_FOR_OUTPUT);
}
/* 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__ (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))
+ 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)
+fmt_check_type_compat (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
caller must eventually free(). VARNAME is optional and only used in the
error message. */
char *
-fmt_check_width_compat__ (const struct fmt_spec *format, const char *varname,
+fmt_check_width_compat__ (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;
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."),
- varname, width, format_str);
- else
+ "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."),
- width, format_str);
+ "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.
- VARNAME is optional and only used in the error message. */
+ returns true if so, otherwise false. */
bool
-fmt_check_width_compat (const struct fmt_spec *format, const char *varname,
- int width)
+fmt_check_width_compat (struct fmt_spec format, int width)
{
- return fmt_emit_and_free_error (fmt_check_width_compat__ (format, varname,
- width));
+ return error_to_bool (fmt_check_width_compat__ (format, NULL, width));
}
/* Returns the width corresponding to FORMAT. The return value
is the width of the `union value's required by FORMAT. */
int
-fmt_var_width (const struct fmt_spec *format)
+fmt_var_width (struct fmt_spec format)
{
- return (format->type == FMT_AHEX ? format->w / 2
- : format->type == FMT_A ? format->w
+ return (format.type == FMT_AHEX ? format.w / 2
+ : format.type == FMT_A ? format.w
: 0);
}
even if F's format type does not allow decimals, to allow
accurately presenting incorrect formats to the user. */
char *
-fmt_to_string (const struct fmt_spec *f, char buffer[FMT_STRING_LEN_MAX + 1])
+fmt_to_string (struct fmt_spec f, char buffer[FMT_STRING_LEN_MAX + 1])
{
- if (fmt_takes_decimals (f->type) || f->d > 0)
+ if (fmt_takes_decimals (f.type) || f.d > 0)
snprintf (buffer, FMT_STRING_LEN_MAX + 1,
- "%s%d.%d", fmt_name (f->type), f->w, f->d);
+ "%s%d.%d", fmt_name (f.type), f.w, f.d);
else
snprintf (buffer, FMT_STRING_LEN_MAX + 1,
- "%s%d", fmt_name (f->type), f->w);
+ "%s%d", fmt_name (f.type), f.w);
return buffer;
}
/* Returns true if A and B are identical formats,
false otherwise. */
bool
-fmt_equal (const struct fmt_spec *a, const struct fmt_spec *b)
+fmt_equal (struct fmt_spec a, struct fmt_spec b)
{
- return a->type == b->type && a->w == b->w && a->d == b->d;
+ return a.type == b.type && a.w == b.w && a.d == b.d;
}
/* Adjusts FMT to be valid for a value of the given WIDTH if necessary.
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, NULL, 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,