44 |
in the current token on success or to a null pointer on |
in the current token on success or to a null pointer on |
45 |
failure. */ |
failure. */ |
46 |
int |
int |
47 |
parse_format_specifier_name (const char **cp, int allow_xt) |
parse_format_specifier_name (const char **cp, enum fmt_parse_flags flags) |
48 |
{ |
{ |
49 |
char *sp, *ep; |
char *sp, *ep; |
50 |
int idx; |
int idx; |
64 |
/* Check format. */ |
/* Check format. */ |
65 |
if (idx < FMT_NUMBER_OF_FORMATS) |
if (idx < FMT_NUMBER_OF_FORMATS) |
66 |
{ |
{ |
67 |
if (!allow_xt && (idx == FMT_T || idx == FMT_X)) |
if (!(flags & FMTP_ALLOW_XT) && (idx == FMT_T || idx == FMT_X)) |
68 |
{ |
{ |
69 |
msg (SE, _("X and T format specifiers not allowed here.")); |
if (!(flags & FMTP_SUPPRESS_ERRORS)) |
70 |
|
msg (SE, _("X and T format specifiers not allowed here.")); |
71 |
idx = -1; |
idx = -1; |
72 |
} |
} |
73 |
} |
} |
74 |
else |
else |
75 |
{ |
{ |
76 |
/* No match. */ |
/* No match. */ |
77 |
msg (SE, _("%.*s is not a valid data format."), |
if (!(flags & FMTP_SUPPRESS_ERRORS)) |
78 |
(int) (ep - sp), ds_c_str (&tokstr)); |
msg (SE, _("%.*s is not a valid data format."), |
79 |
|
(int) (ep - sp), ds_c_str (&tokstr)); |
80 |
idx = -1; |
idx = -1; |
81 |
} |
} |
82 |
} |
} |
112 |
} |
} |
113 |
|
|
114 |
/* Checks whether SPEC is valid as an input format and returns |
/* Checks whether SPEC is valid as an input format and returns |
115 |
nonzero if so. Otherwise, emits an error message and returns |
nonzero if so. Otherwise, emits an error message (if |
116 |
zero. */ |
EMIT_ERROR is nonzero) and returns zero. */ |
117 |
int |
int |
118 |
check_input_specifier (const struct fmt_spec *spec) |
check_input_specifier (const struct fmt_spec *spec, int emit_error) |
119 |
{ |
{ |
120 |
struct fmt_desc *f; |
struct fmt_desc *f; |
121 |
char *str; |
char *str; |
126 |
return 1; |
return 1; |
127 |
if (f->cat & FCAT_OUTPUT_ONLY) |
if (f->cat & FCAT_OUTPUT_ONLY) |
128 |
{ |
{ |
129 |
msg (SE, _("Format %s may not be used as an input format."), f->name); |
if (emit_error) |
130 |
|
msg (SE, _("Format %s may not be used as an input format."), f->name); |
131 |
return 0; |
return 0; |
132 |
} |
} |
133 |
if (spec->w < f->Imin_w || spec->w > f->Imax_w) |
if (spec->w < f->Imin_w || spec->w > f->Imax_w) |
134 |
{ |
{ |
135 |
msg (SE, _("Input format %s specifies a bad width %d. " |
if (emit_error) |
136 |
"Format %s requires a width between %d and %d."), |
msg (SE, _("Input format %s specifies a bad width %d. " |
137 |
str, spec->w, f->name, f->Imin_w, f->Imax_w); |
"Format %s requires a width between %d and %d."), |
138 |
|
str, spec->w, f->name, f->Imin_w, f->Imax_w); |
139 |
return 0; |
return 0; |
140 |
} |
} |
141 |
if ((f->cat & FCAT_EVEN_WIDTH) && spec->w % 2) |
if ((f->cat & FCAT_EVEN_WIDTH) && spec->w % 2) |
142 |
{ |
{ |
143 |
msg (SE, _("Input format %s specifies an odd width %d, but " |
if (emit_error) |
144 |
"format %s requires an even width between %d and " |
msg (SE, _("Input format %s specifies an odd width %d, but " |
145 |
"%d."), str, spec->w, f->name, f->Imin_w, f->Imax_w); |
"format %s requires an even width between %d and " |
146 |
|
"%d."), str, spec->w, f->name, f->Imin_w, f->Imax_w); |
147 |
return 0; |
return 0; |
148 |
} |
} |
149 |
if (f->n_args > 1 && (spec->d < 0 || spec->d > 16)) |
if (f->n_args > 1 && (spec->d < 0 || spec->d > 16)) |
150 |
{ |
{ |
151 |
msg (SE, _("Input format %s specifies a bad number of " |
if (emit_error) |
152 |
"implied decimal places %d. Input format %s allows " |
msg (SE, _("Input format %s specifies a bad number of " |
153 |
"up to 16 implied decimal places."), str, spec->d, f->name); |
"implied decimal places %d. Input format %s allows " |
154 |
|
"up to 16 implied decimal places."), str, spec->d, f->name); |
155 |
return 0; |
return 0; |
156 |
} |
} |
157 |
return 1; |
return 1; |
158 |
} |
} |
159 |
|
|
160 |
/* Checks whether SPEC is valid as an output format and returns |
/* Checks whether SPEC is valid as an output format and returns |
161 |
nonzero if so. Otherwise, emits an error message and returns |
nonzero if so. Otherwise, emits an error message (if |
162 |
zero. */ |
EMIT_ERROR is nonzero) and returns zero. */ |
163 |
int |
int |
164 |
check_output_specifier (const struct fmt_spec *spec) |
check_output_specifier (const struct fmt_spec *spec, int emit_error) |
165 |
{ |
{ |
166 |
struct fmt_desc *f; |
struct fmt_desc *f; |
167 |
char *str; |
char *str; |
172 |
return 1; |
return 1; |
173 |
if (spec->w < f->Omin_w || spec->w > f->Omax_w) |
if (spec->w < f->Omin_w || spec->w > f->Omax_w) |
174 |
{ |
{ |
175 |
msg (SE, _("Output format %s specifies a bad width %d. " |
if (emit_error) |
176 |
"Format %s requires a width between %d and %d."), |
msg (SE, _("Output format %s specifies a bad width %d. " |
177 |
str, spec->w, f->name, f->Omin_w, f->Omax_w); |
"Format %s requires a width between %d and %d."), |
178 |
|
str, spec->w, f->name, f->Omin_w, f->Omax_w); |
179 |
return 0; |
return 0; |
180 |
} |
} |
181 |
if (spec->d > 1 |
if (spec->d > 1 |
183 |
|| spec->type == FMT_DOLLAR) |
|| spec->type == FMT_DOLLAR) |
184 |
&& spec->w < f->Omin_w + 1 + spec->d) |
&& spec->w < f->Omin_w + 1 + spec->d) |
185 |
{ |
{ |
186 |
msg (SE, _("Output format %s requires minimum width %d to allow " |
if (emit_error) |
187 |
"%d decimal places. Try %s%d.%d instead of %s."), |
msg (SE, _("Output format %s requires minimum width %d to allow " |
188 |
f->name, f->Omin_w + 1 + spec->d, spec->d, f->name, |
"%d decimal places. Try %s%d.%d instead of %s."), |
189 |
f->Omin_w + 1 + spec->d, spec->d, str); |
f->name, f->Omin_w + 1 + spec->d, spec->d, f->name, |
190 |
|
f->Omin_w + 1 + spec->d, spec->d, str); |
191 |
return 0; |
return 0; |
192 |
} |
} |
193 |
if ((f->cat & FCAT_EVEN_WIDTH) && spec->w % 2) |
if ((f->cat & FCAT_EVEN_WIDTH) && spec->w % 2) |
194 |
{ |
{ |
195 |
msg (SE, _("Output format %s specifies an odd width %d, but " |
if (emit_error) |
196 |
"output format %s requires an even width between %d and " |
msg (SE, _("Output format %s specifies an odd width %d, but " |
197 |
"%d."), str, spec->w, f->name, f->Omin_w, f->Omax_w); |
"output format %s requires an even width between %d and " |
198 |
|
"%d."), str, spec->w, f->name, f->Omin_w, f->Omax_w); |
199 |
return 0; |
return 0; |
200 |
} |
} |
201 |
if (f->n_args > 1 && (spec->d < 0 || spec->d > 16)) |
if (f->n_args > 1 && (spec->d < 0 || spec->d > 16)) |
202 |
{ |
{ |
203 |
msg (SE, _("Output format %s specifies a bad number of " |
if (emit_error) |
204 |
"implied decimal places %d. Output format %s allows " |
msg (SE, _("Output format %s specifies a bad number of " |
205 |
"a number of implied decimal places between 1 " |
"implied decimal places %d. Output format %s allows " |
206 |
"and 16."), str, spec->d, f->name); |
"a number of implied decimal places between 1 " |
207 |
|
"and 16."), str, spec->d, f->name); |
208 |
return 0; |
return 0; |
209 |
} |
} |
210 |
return 1; |
return 1; |
326 |
check_output_specifier() on the parsed format as |
check_output_specifier() on the parsed format as |
327 |
necessary. */ |
necessary. */ |
328 |
int |
int |
329 |
parse_format_specifier (struct fmt_spec *input, int allow_xt) |
parse_format_specifier (struct fmt_spec *input, enum fmt_parse_flags flags) |
330 |
{ |
{ |
331 |
struct fmt_spec spec; |
struct fmt_spec spec; |
332 |
struct fmt_desc *f; |
struct fmt_desc *f; |
336 |
|
|
337 |
if (token != T_ID) |
if (token != T_ID) |
338 |
{ |
{ |
339 |
msg (SE, _("Format specifier expected.")); |
if (!(flags & FMTP_SUPPRESS_ERRORS)) |
340 |
|
msg (SE, _("Format specifier expected.")); |
341 |
return 0; |
return 0; |
342 |
} |
} |
343 |
type = parse_format_specifier_name (&cp, allow_xt); |
type = parse_format_specifier_name (&cp, flags); |
344 |
if (type == -1) |
if (type == -1) |
345 |
return 0; |
return 0; |
346 |
f = &formats[type]; |
f = &formats[type]; |
348 |
w = strtol (cp, &cp2, 10); |
w = strtol (cp, &cp2, 10); |
349 |
if (cp2 == cp && type != FMT_X) |
if (cp2 == cp && type != FMT_X) |
350 |
{ |
{ |
351 |
msg (SE, _("Data format %s does not specify a width."), |
if (!(flags & FMTP_SUPPRESS_ERRORS)) |
352 |
ds_c_str (&tokstr)); |
msg (SE, _("Data format %s does not specify a width."), |
353 |
|
ds_c_str (&tokstr)); |
354 |
return 0; |
return 0; |
355 |
} |
} |
356 |
|
|
366 |
|
|
367 |
if (*cp) |
if (*cp) |
368 |
{ |
{ |
369 |
msg (SE, _("Data format %s is not valid."), ds_c_str (&tokstr)); |
if (!(flags & FMTP_SUPPRESS_ERRORS)) |
370 |
|
msg (SE, _("Data format %s is not valid."), ds_c_str (&tokstr)); |
371 |
return 0; |
return 0; |
372 |
} |
} |
373 |
lex_get (); |
lex_get (); |