| 241 | report an error and exit. */ |
| 242 | |
| 243 | static char const * |
| 244 | long_double_format (char const *fmt, struct layout *layout) |
| 245 | { |
| 246 | size_t i; |
| 247 | size_t prefix_len = 0; |
| 248 | |
| 249 | for (i = 0; ! (fmt[i] == '%' && fmt[i + 1] != '%'); i += (fmt[i] == '%') + 1) |
| 250 | { |
| 251 | if (!fmt[i]) |
| 252 | error (EXIT_FAILURE, 0, |
| 253 | _("format %s has no %% directive"), quote (fmt)); |
| 254 | prefix_len++; |
| 255 | } |
| 256 | |
| 257 | i++; |
| 258 | i += strspn (fmt + i, "-+#0 '"); |
| 259 | i += strspn (fmt + i, "0123456789"); |
| 260 | if (fmt[i] == '.') |
| 261 | { |
| 262 | i++; |
| 263 | i += strspn (fmt + i, "0123456789"); |
| 264 | } |
| 265 | |
| 266 | size_t length_modifier_offset = i; |
| 267 | bool has_L = (fmt[i] == 'L'); |
| 268 | i += has_L; |
| 269 | if (fmt[i] == '\0') |
| 270 | error (EXIT_FAILURE, 0, _("format %s ends in %%"), quote (fmt)); |
| 271 | if (! strchr ("efgaEFGA", fmt[i])) |
| 272 | error (EXIT_FAILURE, 0, |
| 273 | _("format %s has unknown %%%c directive"), quote (fmt), fmt[i]); |
| 274 | |
| 275 | size_t suffix_len = 0; |
| 276 | for (i++; ; i += (fmt[i] == '%') + 1) |
| 277 | if (fmt[i] == '%' && fmt[i + 1] != '%') |
| 278 | error (EXIT_FAILURE, 0, _("format %s has too many %% directives"), |
| 279 | quote (fmt)); |
| 280 | else if (fmt[i]) |
| 281 | suffix_len++; |
| 282 | else |
| 283 | { |
| 284 | size_t format_size = i + 1; |
| 285 | char *ldfmt = xmalloc (format_size + 1); |
| 286 | memcpy (ldfmt, fmt, length_modifier_offset); |
| 287 | ldfmt[length_modifier_offset] = 'L'; |
| 288 | strcpy (ldfmt + length_modifier_offset + 1, |
| 289 | fmt + length_modifier_offset + has_L); |
| 290 | layout->prefix_len = prefix_len; |
| 291 | layout->suffix_len = suffix_len; |
| 292 | return ldfmt; |
| 293 | } |
| 294 | } |
| 295 | |
| 296 | /* Actually print the sequence of numbers in the specified range, with the |
| 297 | given or default stepping and format. */ |