/* EAM Nov 2012: * Unbelievably, the count parameter has been silently ignored or * improperly applied ever since this routine was introduced back * in version 3.7. Now fixed to prevent buffer overflow. */ void gprintf( char *outstring, size_t count, char *format, double log10_base, double x) { char tempdest[MAX_LINE_LEN + 1]; char temp[MAX_LINE_LEN + 1]; char *t; TBOOLEAN seen_mantissa = FALSE; /* remember if mantissa was already output */ double stored_power_base = 0; /* base for the last mantissa output*/ int stored_power = 0; /* power matching the mantissa output earlier */ TBOOLEAN got_hash = FALSE; char *dest = &tempdest[0]; char *limit = &tempdest[MAX_LINE_LEN]; static double log10_of_1024; /* to avoid excess precision comparison in check of connection %b -- %B */ log10_of_1024 = log10(1024); #define remaining_space (size_t)(limit-dest) *dest = '\0'; set_numeric_locale(); /* Oct 2013 - default format is now expected to be "%h" */ if (((term->flags & TERM_IS_LATEX)) && !strcmp(format, DEF_FORMAT)) format = DEF_FORMAT_LATEX; for (;;) { /*{{{ copy to dest until % */ while (*format != '%') if (!(*dest++ = *format++) || (remaining_space == 0)) { goto done; } /*}}} */ /*{{{ check for %% */ if (format[1] == '%') { *dest++ = '%'; format += 2; continue; } /*}}} */ /*{{{ copy format part to temp, excluding conversion character */ t = temp; *t++ = '%'; if (format[1] == '#') { *t++ = '#'; format++; got_hash = TRUE; } /* dont put isdigit first since side effect in macro is bad */ while (*++format == '.' || isdigit((unsigned char) *format) || *format == '-' || *format == '+' || *format == ' ' || *format == '\'') *t++ = *format; /*}}} */ /*{{{ convert conversion character */ switch (*format) { /*{{{ x and o */ case 'x': case 'X': case 'o': case 'O': if (fabs(x) >= (double)INT_MAX) { t[0] = 'l'; t[1] = 'l'; t[2] = *format; t[3] = '\0'; snprintf(dest, remaining_space, temp, (long long) x); } else { t[0] = *format; t[1] = '\0'; snprintf(dest, remaining_space, temp, (int) x); } break; /*}}} */ /*{{{ e, f and g */ case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': t[0] = *format; t[1] = 0; snprintf(dest, remaining_space, temp, x); break; case 'h': case 'H': /* g/G with enhanced formating (if applicable) */ t[0] = (*format == 'h') ? 'g' : 'G'; t[1] = 0; if ((term->flags & (TERM_ENHANCED_TEXT | TERM_IS_LATEX)) == 0) { /* Not enhanced, not latex, just print it */ snprintf(dest, remaining_space, temp, x); } else if (table_mode) { /* Tabular output should contain no markup */ snprintf(dest, remaining_space, temp, x); } else { /* in enhanced mode -- convert E/e to x10^{foo} or *10^{foo} */ #define LOCAL_BUFFER_SIZE 256 char tmp[LOCAL_BUFFER_SIZE]; char tmp2[LOCAL_BUFFER_SIZE]; int i,j; TBOOLEAN bracket_flag = FALSE; snprintf(tmp, 240, temp, x); /* magic number alert: why 240? */ for (i=j=0; tmp[i] && (i < LOCAL_BUFFER_SIZE); i++) { if (tmp[i]=='E' || tmp[i]=='e') { if ((term-> flags & TERM_IS_LATEX)) { if (*format == 'h') { strcpy(&tmp2[j], "\\times"); j+= 6; } else { strcpy(&tmp2[j], "\\cdot"); j+= 5; } } else switch (encoding) { case S_ENC_UTF8: strcpy(&tmp2[j], "\xc3\x97"); /* UTF character '×' */ j+= 2; break; case S_ENC_CP1252: tmp2[j++] = (*format=='h') ? 0xd7 : 0xb7; break; case S_ENC_ISO8859_1: case S_ENC_ISO8859_2: case S_ENC_ISO8859_9: case S_ENC_ISO8859_15: tmp2[j++] = (*format=='h') ? 0xd7 : '*'; break; default: tmp2[j++] = (*format=='h') ? 'x' : '*'; break; } strcpy(&tmp2[j], "10^{"); j += 4; bracket_flag = TRUE; /* Skip + and leading 0 in exponent */ i++; /* skip E */ if (tmp[i] == '+') i++; else if (tmp[i] == '-') /* copy sign */ tmp2[j++] = tmp[i++]; while (tmp[i] == '0') i++; i--; /* undo following loop increment */ } else { tmp2[j++] = tmp[i]; } } if (bracket_flag) tmp2[j++] = '}'; tmp2[j] = '\0'; strncpy(dest, tmp2, remaining_space); #undef LOCAL_BUFFER_SIZE } break; /*}}} */ /*{{{ l --- mantissa to current log base */ case 'l': { double mantissa; t[0] = 'f'; t[1] = 0; stored_power_base = log10_base; mant_exp(stored_power_base, x, FALSE, &mantissa, &stored_power, temp); seen_mantissa = TRUE; snprintf(dest, remaining_space, temp, mantissa); break; } /*}}} */ /*{{{ t --- base-10 mantissa */ case 't': { double mantissa; t[0] = 'f'; t[1] = 0; stored_power_base = 1.0; mant_exp(stored_power_base, x, FALSE, &mantissa, &stored_power, temp); seen_mantissa = TRUE; snprintf(dest, remaining_space, temp, mantissa); break; } /*}}} */ /*{{{ s --- base-1000 / 'scientific' mantissa */ case 's': { double mantissa; t[0] = 'f'; t[1] = 0; stored_power_base = 1.0; mant_exp(stored_power_base, x, TRUE, &mantissa, &stored_power, temp); seen_mantissa = TRUE; snprintf(dest, remaining_space, temp, mantissa); break; } /*}}} */ /*{{{ b --- base-1024 mantissa */ case 'b': { double mantissa; t[0] = 'f'; t[1] = 0; stored_power_base = log10_of_1024; mant_exp(stored_power_base, x, FALSE, &mantissa, &stored_power, temp); seen_mantissa = TRUE; snprintf(dest, remaining_space, temp, mantissa); break; } /*}}} */ /*{{{ L --- power to current log base */ case 'L': { int power; t[0] = 'd'; t[1] = 0; if (seen_mantissa) { if (stored_power_base == log10_base) { power = stored_power; } else { int_error(NO_CARET, "Format character mismatch: %%L is only valid with %%l"); } } else { stored_power_base = log10_base; mant_exp(log10_base, x, FALSE, NULL, &power, "%.0f"); } snprintf(dest, remaining_space, temp, power); break; } /*}}} */ /*{{{ T --- power of ten */ case 'T': { int power; t[0] = 'd'; t[1] = 0; if (seen_mantissa) { if (stored_power_base == 1.0) { power = stored_power; } else { int_error(NO_CARET, "Format character mismatch: %%T is only valid with %%t"); } } else { mant_exp(1.0, x, FALSE, NULL, &power, "%.0f"); } snprintf(dest, remaining_space, temp, power); break; } /*}}} */ /*{{{ S --- power of 1000 / 'scientific' */ case 'S': { int power; t[0] = 'd'; t[1] = 0; if (seen_mantissa) { if (stored_power_base == 1.0) { power = stored_power; } else { int_error(NO_CARET, "Format character mismatch: %%S is only valid with %%s"); } } else { mant_exp(1.0, x, TRUE, NULL, &power, "%.0f"); } snprintf(dest, remaining_space, temp, power); break; } /*}}} */ /*{{{ c --- ISO decimal unit prefix letters */ case 'c': { int power; t[0] = 'c'; t[1] = 0; if (seen_mantissa) { if (stored_power_base == 1.0) { power = stored_power; } else { int_error(NO_CARET, "Format character mismatch: %%c is only valid with %%s"); } } else { mant_exp(1.0, x, TRUE, NULL, &power, "%.0f"); } if (power >= -24 && power <= 24) { /* name power name power ------------------------- yocto -24 yotta 24 zepto -21 zetta 21 atto -18 Exa 18 femto -15 Peta 15 pico -12 Tera 12 nano -9 Giga 9 micro -6 Mega 6 milli -3 kilo 3 */ /* -18 -> 0, 0 -> 6, +18 -> 12, ... */ /* HBB 20010121: avoid division of -ve ints! */ power = (power + 24) / 3; snprintf(dest, remaining_space, temp, "yzafpnum kMGTPEZY"[power]); } else { /* please extend the range ! */ /* fall back to simple exponential */ snprintf(dest, remaining_space, "e%+02d", power); } break; } /*}}} */ /*{{{ B --- IEC 60027-2 A.2 / ISO/IEC 80000 binary unit prefix letters */ case 'B': { int power; t[0] = 'c'; t[1] = 'i'; t[2] = '\0'; if (seen_mantissa) { if (stored_power_base == log10_of_1024) { power = stored_power; } else { int_error(NO_CARET, "Format character mismatch: %%B is only valid with %%b"); } } else { mant_exp(log10_of_1024, x, FALSE, NULL, &power, "%.0f"); } if (power > 0 && power <= 8) { /* name power ----------- Yobi 8 Zebi 7 Exbi 9 Pebi 5 Tebi 4 Gibi 3 Mebi 2 kibi 1 */ snprintf(dest, remaining_space, temp, " kMGTPEZY"[power]); } else if (power > 8) { /* for the larger values, print x2^{10}Gi for example */ snprintf(dest, remaining_space, "x2^{%d}Yi", power-8); } else if (power < 0) { snprintf(dest, remaining_space, "x2^{%d}", power*10); } else { snprintf(dest, remaining_space, " "); } break; } /*}}} */ /*{{{ P --- multiple of pi */ case 'P': { t[0] = 'f'; t[1] = 0; snprintf(dest, remaining_space, temp, x / M_PI); break; } /*}}} */ default: reset_numeric_locale(); int_error(NO_CARET, "Bad format character"); } /* switch */ /*}}} */ if (got_hash && (format != strpbrk(format,"oeEfFgG"))) { reset_numeric_locale(); int_error(NO_CARET, "Bad format character"); } /* change decimal '.' to the actual entry in decimalsign */ if (decimalsign != NULL) { char *dotpos1 = dest; char *dotpos2; size_t newlength = strlen(decimalsign); /* dot is the default decimalsign we will be replacing */ int dot = *get_decimal_locale(); /* replace every dot by the contents of decimalsign */ while ((dotpos2 = strchr(dotpos1,dot)) != NULL) { if (newlength == 1) { /* The normal case */ *dotpos2 = *decimalsign; dotpos1++; } else { /* Some multi-byte decimal marker */ size_t taillength = strlen(dotpos2); dotpos1 = dotpos2 + newlength; if (dotpos1 + taillength > limit) int_error(NO_CARET, "format too long due to decimalsign string"); /* move tail end of string out of the way */ memmove(dotpos1, dotpos2 + 1, taillength); /* insert decimalsign */ memcpy(dotpos2, decimalsign, newlength); } } } /* this was at the end of every single case, before: */ dest += strlen(dest); ++format; } /* for ever */ done: #if (0) /* Oct 2013 - Not safe because it fails to recognize LaTeX macros. */ /* For LaTeX terminals, if the user has not already provided a */ /* format in math mode, wrap whatever we got by default in $...$ */ if (((term->flags & TERM_IS_LATEX)) && !strchr(tempdest, '$')) { *(outstring++) = '$'; strcat(tempdest, "$"); count -= 2; } #endif /* Copy as much as fits */ safe_strncpy(outstring, tempdest, count); reset_numeric_locale(); }
/* HBB 20010121: added code to maintain consistency between mantissa * and exponent across sprintf() calls. The problem: format string * '%t*10^%T' will display 9.99 as '10.0*10^0', but 10.01 as * '1.0*10^1'. This causes problems for people using the %T part, * only, with logscaled axes, in combination with the occasional * round-off error. */ void gprintf( char *dest, size_t count, char *format, double log10_base, double x) { char temp[MAX_LINE_LEN + 1]; char *t; TBOOLEAN seen_mantissa = FALSE; /* memorize if mantissa has been output, already */ int stored_power = 0; /* power that matches the mantissa output earlier */ set_numeric_locale(); for (;;) { /*{{{ copy to dest until % */ while (*format != '%') if (!(*dest++ = *format++)) { reset_numeric_locale(); return; /* end of format */ } /*}}} */ /*{{{ check for %% */ if (format[1] == '%') { *dest++ = '%'; format += 2; continue; } /*}}} */ /*{{{ copy format part to temp, excluding conversion character */ t = temp; *t++ = '%'; /* dont put isdigit first since sideeffect in macro is bad */ while (*++format == '.' || isdigit((unsigned char) *format) || *format == '-' || *format == '+' || *format == ' ' || *format == '\'') *t++ = *format; /*}}} */ /*{{{ convert conversion character */ switch (*format) { /*{{{ x and o */ case 'x': case 'X': case 'o': case 'O': t[0] = *format; t[1] = 0; sprintf(dest, temp, (int) x); break; /*}}} */ /*{{{ e, f and g */ case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': t[0] = *format; t[1] = 0; sprintf(dest, temp, x); break; /*}}} */ /*{{{ l --- mantissa to current log base */ case 'l': { double mantissa; t[0] = 'f'; t[1] = 0; mant_exp(log10_base, x, FALSE, &mantissa, &stored_power, temp); seen_mantissa = TRUE; sprintf(dest, temp, mantissa); break; } /*}}} */ /*{{{ t --- base-10 mantissa */ case 't': { double mantissa; t[0] = 'f'; t[1] = 0; mant_exp(1.0, x, FALSE, &mantissa, &stored_power, temp); seen_mantissa = TRUE; sprintf(dest, temp, mantissa); break; } /*}}} */ /*{{{ s --- base-1000 / 'scientific' mantissa */ case 's': { double mantissa; t[0] = 'f'; t[1] = 0; mant_exp(1.0, x, TRUE, &mantissa, &stored_power, temp); seen_mantissa = TRUE; sprintf(dest, temp, mantissa); break; } /*}}} */ /*{{{ L --- power to current log base */ case 'L': { int power; t[0] = 'd'; t[1] = 0; if (seen_mantissa) power = stored_power; else mant_exp(log10_base, x, FALSE, NULL, &power, "%.0f"); sprintf(dest, temp, power); break; } /*}}} */ /*{{{ T --- power of ten */ case 'T': { int power; t[0] = 'd'; t[1] = 0; if (seen_mantissa) power = stored_power; else mant_exp(1.0, x, FALSE, NULL, &power, "%.0f"); sprintf(dest, temp, power); break; } /*}}} */ /*{{{ S --- power of 1000 / 'scientific' */ case 'S': { int power; t[0] = 'd'; t[1] = 0; if (seen_mantissa) power = stored_power; else mant_exp(1.0, x, TRUE, NULL, &power, "%.0f"); sprintf(dest, temp, power); break; } /*}}} */ /*{{{ c --- ISO decimal unit prefix letters */ case 'c': { int power; t[0] = 'c'; t[1] = 0; if (seen_mantissa) power = stored_power; else mant_exp(1.0, x, TRUE, NULL, &power, "%.0f"); if (power >= -18 && power <= 18) { /* -18 -> 0, 0 -> 6, +18 -> 12, ... */ /* HBB 20010121: avoid division of -ve ints! */ power = (power + 18) / 3; sprintf(dest, temp, "afpnum kMGTPE"[power]); } else { /* please extend the range ! */ /* name power name power ------------------------- atto -18 Exa 18 femto -15 Peta 15 pico -12 Tera 12 nano -9 Giga 9 micro -6 Mega 6 milli -3 kilo 3 */ /* for the moment, print e+21 for example */ sprintf(dest, "e%+02d", (power - 6) * 3); } break; } /*}}} */ /*{{{ P --- multiple of pi */ case 'P': { t[0] = 'f'; t[1] = 0; sprintf(dest, temp, x / M_PI); break; } /*}}} */ default: reset_numeric_locale(); int_error(NO_CARET, "Bad format character"); } /* switch */ /*}}} */ /* change decimal `.' to the actual entry in decimalsign */ if (decimalsign != NULL) { char *dotpos1 = dest, *dotpos2; size_t newlength = strlen(decimalsign); int dot; /* dot is the default decimalsign we will be replacing */ dot = *get_decimal_locale(); /* replace every dot by the contents of decimalsign */ while ((dotpos2 = strchr(dotpos1,dot)) != NULL) { size_t taillength = strlen(dotpos2); dotpos1 = dotpos2 + newlength; /* test if the new value for dest would be too long */ if (dotpos1 - dest + taillength > count) int_error(NO_CARET, "format too long due to long decimalsign string"); /* move tail end of string out of the way */ memmove(dotpos1, dotpos2 + 1, taillength); /* insert decimalsign */ memcpy(dotpos2, decimalsign, newlength); } /* clear temporary variables for safety */ dotpos1=NULL; dotpos2=NULL; } /* this was at the end of every single case, before: */ dest += strlen(dest); ++format; } /* for ever */ reset_numeric_locale(); }
/* EAM Nov 2012: * Unbelievably, the count parameter has been silently ignored or * improperly applied ever since this routine was introduced back * in version 3.7. Now fixed to prevent buffer overflow. */ void gprintf( char *outstring, size_t count, char *format, double log10_base, double x) { char tempdest[MAX_LINE_LEN + 1]; char temp[MAX_LINE_LEN + 1]; char *t; TBOOLEAN seen_mantissa = FALSE; /* remember if mantissa was already output */ double stored_power_base = 0; /* base for the last mantissa output*/ int stored_power = 0; /* power matching the mantissa output earlier */ TBOOLEAN got_hash = FALSE; char *dest = &tempdest[0]; char *limit = &tempdest[MAX_LINE_LEN]; #define remaining_space (size_t)(limit-dest) *dest = '\0'; set_numeric_locale(); for (;;) { /*{{{ copy to dest until % */ while (*format != '%') if (!(*dest++ = *format++) || (remaining_space == 0)) { safe_strncpy(outstring,tempdest,count); reset_numeric_locale(); return; /* end of format */ } /*}}} */ /*{{{ check for %% */ if (format[1] == '%') { *dest++ = '%'; format += 2; continue; } /*}}} */ /*{{{ copy format part to temp, excluding conversion character */ t = temp; *t++ = '%'; if (format[1] == '#') { *t++ = '#'; format++; got_hash = TRUE; } /* dont put isdigit first since sideeffect in macro is bad */ while (*++format == '.' || isdigit((unsigned char) *format) || *format == '-' || *format == '+' || *format == ' ' || *format == '\'') *t++ = *format; /*}}} */ /*{{{ convert conversion character */ switch (*format) { /*{{{ x and o */ case 'x': case 'X': case 'o': case 'O': if (fabs(x) >= (double)INT_MAX) { t[0] = 'l'; t[1] = 'l'; t[2] = *format; t[3] = '\0'; snprintf(dest, remaining_space, temp, (long long) x); } else { t[0] = *format; t[1] = '\0'; snprintf(dest, remaining_space, temp, (int) x); } break; /*}}} */ /*{{{ e, f and g */ case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': t[0] = *format; t[1] = 0; snprintf(dest, remaining_space, temp, x); break; /*}}} */ /*{{{ l --- mantissa to current log base */ case 'l': { double mantissa; t[0] = 'f'; t[1] = 0; stored_power_base = log10_base; mant_exp(stored_power_base, x, FALSE, &mantissa, &stored_power, temp); seen_mantissa = TRUE; snprintf(dest, remaining_space, temp, mantissa); break; } /*}}} */ /*{{{ t --- base-10 mantissa */ case 't': { double mantissa; t[0] = 'f'; t[1] = 0; stored_power_base = 1.0; mant_exp(stored_power_base, x, FALSE, &mantissa, &stored_power, temp); seen_mantissa = TRUE; snprintf(dest, remaining_space, temp, mantissa); break; } /*}}} */ /*{{{ s --- base-1000 / 'scientific' mantissa */ case 's': { double mantissa; t[0] = 'f'; t[1] = 0; stored_power_base = 1.0; mant_exp(stored_power_base, x, TRUE, &mantissa, &stored_power, temp); seen_mantissa = TRUE; snprintf(dest, remaining_space, temp, mantissa); break; } /*}}} */ /*{{{ b --- base-1024 mantissa */ case 'b': { double mantissa; t[0] = 'f'; t[1] = 0; stored_power_base = log10(1024); mant_exp(stored_power_base, x, FALSE, &mantissa, &stored_power, temp); seen_mantissa = TRUE; snprintf(dest, remaining_space, temp, mantissa); break; } /*}}} */ /*{{{ L --- power to current log base */ case 'L': { int power; t[0] = 'd'; t[1] = 0; if (seen_mantissa) if (stored_power_base == log10_base) power = stored_power; else int_error(NO_CARET, "Format character mismatch: %%L is only valid with %%l"); else stored_power_base = log10_base; mant_exp(log10_base, x, FALSE, NULL, &power, "%.0f"); snprintf(dest, remaining_space, temp, power); break; } /*}}} */ /*{{{ T --- power of ten */ case 'T': { int power; t[0] = 'd'; t[1] = 0; if (seen_mantissa) if (stored_power_base == 1.0) power = stored_power; else int_error(NO_CARET, "Format character mismatch: %%T is only valid with %%t"); else mant_exp(1.0, x, FALSE, NULL, &power, "%.0f"); snprintf(dest, remaining_space, temp, power); break; } /*}}} */ /*{{{ S --- power of 1000 / 'scientific' */ case 'S': { int power; t[0] = 'd'; t[1] = 0; if (seen_mantissa) if (stored_power_base == 1.0) power = stored_power; else int_error(NO_CARET, "Format character mismatch: %%S is only valid with %%s"); else mant_exp(1.0, x, TRUE, NULL, &power, "%.0f"); snprintf(dest, remaining_space, temp, power); break; } /*}}} */ /*{{{ c --- ISO decimal unit prefix letters */ case 'c': { int power; t[0] = 'c'; t[1] = 0; if (seen_mantissa) if (stored_power_base == 1.0) power = stored_power; else int_error(NO_CARET, "Format character mismatch: %%c is only valid with %%s"); else mant_exp(1.0, x, TRUE, NULL, &power, "%.0f"); if (power >= -24 && power <= 24) { /* -18 -> 0, 0 -> 6, +18 -> 12, ... */ /* HBB 20010121: avoid division of -ve ints! */ power = (power + 24) / 3; snprintf(dest, remaining_space, temp, "yzafpnum kMGTPEZY"[power]); } else { /* please extend the range ! */ /* name power name power ------------------------- yocto -24 yotta 24 zepto -21 zetta 21 atto -18 Exa 18 femto -15 Peta 15 pico -12 Tera 12 nano -9 Giga 9 micro -6 Mega 6 milli -3 kilo 3 */ /* fall back to simple exponential */ snprintf(dest, remaining_space, "e%+02d", power); } break; } /*}}} */ /*{{{ B --- IEC 60027-2 A.2 / ISO/IEC 80000 binary unit prefix letters */ case 'B': { int power; t[0] = 'c'; t[1] = 'i'; t[2] = 0; if (seen_mantissa) if (stored_power_base == log10(1024)) power = stored_power; else int_error(NO_CARET, "Format character mismatch: %%B is only valid with %%b"); else mant_exp(log10(1024), x, FALSE, NULL, &power, "%.0f"); if (power > 0 && power <= 8) { /* name power ----------- Yobi 8 Zebi 7 Exbi 9 Pebi 5 Tebi 4 Gibi 3 Mebi 2 kibi 1 */ snprintf(dest, remaining_space, temp, " kMGTPEZY"[power]); } else if (power > 8) { /* for the larger values, print x2^{10}Gi for example */ snprintf(dest, remaining_space, "x2^{%d}Yi", power-8); } else if (power < 0) { snprintf(dest, remaining_space, "x2^{%d}", power*10); } break; } /*}}} */ /*{{{ P --- multiple of pi */ case 'P': { t[0] = 'f'; t[1] = 0; snprintf(dest, remaining_space, temp, x / M_PI); break; } /*}}} */ default: reset_numeric_locale(); int_error(NO_CARET, "Bad format character"); } /* switch */ /*}}} */ if (got_hash && (format != strpbrk(format,"oeEfFgG"))) { reset_numeric_locale(); int_error(NO_CARET, "Bad format character"); } /* change decimal `.' to the actual entry in decimalsign */ if (decimalsign != NULL) { char *dotpos1 = dest, *dotpos2; size_t newlength = strlen(decimalsign); int dot; /* dot is the default decimalsign we will be replacing */ dot = *get_decimal_locale(); /* replace every dot by the contents of decimalsign */ while ((dotpos2 = strchr(dotpos1,dot)) != NULL) { size_t taillength = strlen(dotpos2); dotpos1 = dotpos2 + newlength; /* test if the new value for dest would be too long */ if (dotpos1 - dest + taillength > count) int_error(NO_CARET, "format too long due to long decimalsign string"); /* move tail end of string out of the way */ memmove(dotpos1, dotpos2 + 1, taillength); /* insert decimalsign */ memcpy(dotpos2, decimalsign, newlength); } /* clear temporary variables for safety */ dotpos1=NULL; dotpos2=NULL; } /* this was at the end of every single case, before: */ dest += strlen(dest); ++format; } /* for ever */ /* Copy as much as fits */ safe_strncpy(outstring, tempdest, count); reset_numeric_locale(); }