80 # define WORK_SIZE 1024
82 int current_piece = 0;
89 int compass_dir_piece = -1;
93 int deg_has_decpoint = 0;
94 int deg_dec_digits = 0;
99 int min_has_decpoint = 0;
100 int min_dec_digits = 0;
105 int sec_has_decpoint = 0;
106 int sec_dec_digits = 0;
111 int format_length = ((NULL == format) ? 0 : strlen(format));
115 int index, following_byte_index;
116 int multibyte_char_width = 1;
123 pieces[index][0] =
'\0';
127 if (0 == format_length)
130 format =
"D\xC2\xB0""M'S.SSS\"C";
131 format_length = strlen(format);
140 for (index = 0; index < format_length; index++)
142 char next_char = format[index];
149 deg_has_decpoint ? deg_dec_digits++ : deg_digits++;
155 deg_piece = current_piece;
158 lwerror(
"Bad format, cannot include degrees (DD.DDD) more than once.");
170 min_has_decpoint ? min_dec_digits++ : min_digits++;
176 min_piece = current_piece;
179 lwerror(
"Bad format, cannot include minutes (MM.MMM) more than once.");
191 sec_has_decpoint ? sec_dec_digits++ : sec_digits++;
197 sec_piece = current_piece;
200 lwerror(
"Bad format, cannot include seconds (SS.SSS) more than once.");
210 if (reading_deg || reading_min || reading_sec)
219 if (compass_dir_piece >= 0)
221 lwerror(
"Bad format, cannot include compass dir (C) more than once.");
224 compass_dir_piece = current_piece;
231 deg_has_decpoint = 1;
233 else if (reading_min)
235 min_has_decpoint = 1;
237 else if (reading_sec)
239 sec_has_decpoint = 1;
244 strncat(pieces[current_piece], &next_char, 1);
249 if (reading_deg || reading_min || reading_sec)
259 multibyte_char_width = 1;
260 if (next_char & 0x80)
262 if ((next_char & 0xF8) == 0xF0)
264 multibyte_char_width += 3;
266 else if ((next_char & 0xF0) == 0xE0)
268 multibyte_char_width += 2;
270 else if ((next_char & 0xE0) == 0xC0)
272 multibyte_char_width += 1;
276 lwerror(
"Bad format, invalid high-order byte found first, format string may not be UTF-8.");
279 if (multibyte_char_width > 1)
281 if (index + multibyte_char_width >= format_length)
283 lwerror(
"Bad format, UTF-8 character first byte found with insufficient following bytes, format string may not be UTF-8.");
285 for (following_byte_index = (index + 1); following_byte_index < (index + multibyte_char_width); following_byte_index++)
287 if ((format[following_byte_index] & 0xC0) != 0x80)
289 lwerror(
"Bad format, invalid byte found following leading byte of multibyte character, format string may not be UTF-8.");
294 strncat(pieces[current_piece], &(format[index]), multibyte_char_width);
296 index += multibyte_char_width - 1;
301 lwerror(
"Internal error, somehow needed more pieces than it should.");
306 lwerror(
"Bad format, degrees (DD.DDD) must be included.");
319 minutes = modf(val, °rees) * 60;
325 lwerror(
"Bad format, cannot include seconds (SS.SSS) without including minutes (MM.MMM).");
327 seconds = modf(minutes, &minutes) * 60;
331 round_pow = pow(10, sec_dec_digits);
332 if (floorf(seconds * round_pow) / round_pow >= 60)
341 if (compass_dir_piece >= 0)
343 strcpy(pieces[compass_dir_piece], is_negative ? neg_dir_symbol : pos_dir_symbol);
345 else if (is_negative)
351 if (deg_digits + deg_dec_digits + 2 >
WORK_SIZE)
353 lwerror(
"Bad format, degrees (DD.DDD) number of digits was greater than our working limit.");
357 sprintf(pieces[deg_piece],
"%*.*f", deg_digits, deg_dec_digits, degrees);
363 if (min_digits + min_dec_digits + 2 >
WORK_SIZE)
365 lwerror(
"Bad format, minutes (MM.MMM) number of digits was greater than our working limit.");
367 sprintf(pieces[min_piece],
"%*.*f", min_digits, min_dec_digits, minutes);
372 if (sec_digits + sec_dec_digits + 2 >
WORK_SIZE)
374 lwerror(
"Bad format, seconds (SS.SSS) number of digits was greater than our working limit.");
376 sprintf(pieces[sec_piece],
"%*.*f", sec_digits, sec_dec_digits, seconds);
381 memset(result, 0, format_length +
WORK_SIZE);
384 strcpy(result, pieces[0]);
387 strcat(result, pieces[index]);
void * lwalloc(size_t size)
void lwerror(const char *fmt,...)
Write a notice out to the error handler.