fmt_number_style_destroy (settings->ccs[i]);
}
-void
-fmt_settings_copy (struct fmt_settings *new, const struct fmt_settings *old)
+struct fmt_settings
+fmt_settings_copy (const struct fmt_settings *old)
{
- new->epoch = old->epoch;
- new->decimal = old->decimal;
+ struct fmt_settings new = *old;
for (int i = 0; i < FMT_N_CCS; i++)
- new->ccs[i] = fmt_number_style_clone (old->ccs[i]);
+ new.ccs[i] = fmt_number_style_clone (old->ccs[i]);
+ return new;
}
static size_t
struct fmt_spec
fmt_for_input (enum fmt_type type, int w, int d)
{
- struct fmt_spec f;
- f.type = type;
- f.w = w;
- f.d = d;
+ struct fmt_spec f = { .type = type, .w = w, .d = d };
assert (fmt_check_input (&f));
return f;
}
struct fmt_spec
fmt_for_output (enum fmt_type type, int w, int d)
{
- struct fmt_spec f;
- f.type = type;
- f.w = w;
- f.d = d;
+ struct fmt_spec f = { .type = type, .w = w, .d = d };
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 (const struct fmt_spec *input,
+ const struct fmt_settings *settings)
{
struct fmt_spec output;
case FMT_PCT:
{
const struct fmt_number_style *style =
- settings_get_style (input->type);
+ fmt_settings_get_style (settings, input->type);
output.w += fmt_affix_width (style);
if (style->grouping != 0 && input->w - input->d >= 3)
bool
fmt_check (const struct fmt_spec *spec, enum fmt_use use)
{
- const char *io_fmt;
char str[FMT_STRING_LEN_MAX + 1];
int min_w, max_w, max_d;
assert (is_fmt_type (spec->type));
fmt_to_string (spec, str);
- io_fmt = use == FMT_FOR_INPUT ? _("Input format") : _("Output format");
if (use == FMT_FOR_INPUT && !fmt_usable_for_input (spec->type))
{
msg (SE, _("Format %s may not be used for input."), str);
if (spec->w % fmt_step_width (spec->type))
{
assert (fmt_step_width (spec->type) == 2);
- msg (SE, _("%s specifies width %d, but %s requires an even width."),
- str, spec->w, fmt_name (spec->type));
+ if (use == FMT_FOR_INPUT)
+ msg (SE, _("Input format %s specifies width %d, "
+ "but %s requires an even width."),
+ str, spec->w, fmt_name (spec->type));
+ else
+ msg (SE, _("Output format %s specifies width %d, "
+ "but %s requires an even width."),
+ str, spec->w, fmt_name (spec->type));
return false;
}
max_w = fmt_max_width (spec->type, use);
if (spec->w < min_w || spec->w > max_w)
{
- msg (SE, _("%s %s specifies width %d, but "
- "%s requires a width between %d and %d."),
- io_fmt, str, spec->w, fmt_name (spec->type), min_w, max_w);
+ if (use == FMT_FOR_INPUT)
+ msg (SE, _("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);
+ else
+ msg (SE, _("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);
return false;
}
max_d = fmt_max_decimals (spec->type, spec->w, use);
if (!fmt_takes_decimals (spec->type) && spec->d != 0)
{
- msg (SE, ngettext ("%s %s specifies %d decimal place, but "
- "%s does not allow any decimals.",
- "%s %s specifies %d decimal places, but "
- "%s does not allow any decimals.",
- spec->d),
- io_fmt, str, spec->d, fmt_name (spec->type));
+ if (use == FMT_FOR_INPUT)
+ msg (SE, ngettext ("Input format %s specifies %d decimal place, but "
+ "%s does not allow any decimals.",
+ "Input format %s specifies %d decimal places, but "
+ "%s does not allow any decimals.",
+ spec->d),
+ str, spec->d, fmt_name (spec->type));
+ else
+ msg (SE, 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));
return false;
}
else if (spec->d > max_d)
{
if (max_d > 0)
- msg (SE, ngettext ("%s %s specifies %d decimal place, but "
- "the given width allows at most %d decimals.",
- "%s %s specifies %d decimal places, but "
- "the given width allows at most %d decimals.",
- spec->d),
- io_fmt, str, spec->d, max_d);
+ {
+ if (use == FMT_FOR_INPUT)
+ msg (SE, ngettext ("Input format %s specifies %d decimal place, "
+ "but the given width 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);
+ else
+ msg (SE, ngettext ("Output format %s specifies %d decimal place, "
+ "but the given width 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);
+ }
else
- msg (SE, ngettext ("%s %s specifies %d decimal place, but "
- "the given width does not allow for any decimals.",
- "%s %s specifies %d decimal places, but "
- "the given width does not allow for any decimals.",
- spec->d),
- io_fmt, str, spec->d);
+ {
+ if (use == FMT_FOR_INPUT)
+ msg (SE, ngettext ("Input format %s specifies %d decimal place, "
+ "but the given width 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);
+ else
+ msg (SE, ngettext ("Output format %s specifies %d decimal place, "
+ "but the given width 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);
+ }
return false;
}
static void
fmt_clamp_decimals (struct fmt_spec *fmt, enum fmt_use use)
{
- int max_d;
-
- max_d = fmt_max_decimals (fmt->type, fmt->w, use);
- if (fmt->d < 0)
- fmt->d = 0;
- else if (fmt->d > max_d)
+ int max_d = fmt_max_decimals (fmt->type, fmt->w, use);
+ if (fmt->d > max_d)
fmt->d = max_d;
}
\f
fmt_affix_clone (const struct fmt_affix *old)
{
return (struct fmt_affix) {
- .s = old->s ? xstrdup (old->s) : NULL,
+ .s = xstrdup_if_nonnull (old->s),
.width = old->width,
};
}
static void
fmt_affix_free (struct fmt_affix *affix)
{
- if (affix->s[0])
+ if (affix->s)
free (affix->s);
}
return style;
}
+static void
+format_cc (struct string *out, const char *in, char grouping)
+{
+ while (*in != '\0')
+ {
+ char c = *in++;
+ if (c == grouping || c == '\'')
+ ds_put_byte (out, '\'');
+ else if (c == '"')
+ ds_put_byte (out, '"');
+ ds_put_byte (out, c);
+ }
+}
+
+char *
+fmt_number_style_to_string (const struct fmt_number_style *cc)
+{
+ struct string out = DS_EMPTY_INITIALIZER;
+ format_cc (&out, cc->neg_prefix.s, cc->grouping);
+ ds_put_byte (&out, cc->grouping);
+ format_cc (&out, cc->prefix.s, cc->grouping);
+ ds_put_byte (&out, cc->grouping);
+ format_cc (&out, cc->suffix.s, cc->grouping);
+ ds_put_byte (&out, cc->grouping);
+ format_cc (&out, cc->neg_suffix.s, cc->grouping);
+ return ds_steal_cstr (&out);
+}
+
struct fmt_number_style *
fmt_number_style_clone (const struct fmt_number_style *old)
{
return &formats[type];
}
-const struct fmt_spec F_8_0 = {FMT_F, 8, 0};
-const struct fmt_spec F_8_2 = {FMT_F, 8, 2};
-const struct fmt_spec F_4_3 = {FMT_F, 4, 3};
-const struct fmt_spec F_5_1 = {FMT_F, 5, 1};
+const struct fmt_spec F_8_0 = { .type = FMT_F, .w = 8, .d = 0 };
+const struct fmt_spec F_8_2 = { .type = FMT_F, .w = 8, .d = 2 };
+const struct fmt_spec F_4_3 = { .type = FMT_F, .w = 4, .d = 3 };
+const struct fmt_spec F_5_1 = { .type = FMT_F, .w = 5, .d = 1 };