double2string

適当だなぁ。
あとstring2double()もそうだけどstring2double([from], [to])な引数なのがちょっと紛らわしいかも。
1.00000 -> 1とかせずに最初からsnprintf()使わず自前で変換すればうんたらかんたら。

bool
digit2token(double digit, char *str, size_t max_size)
{
    if (snprintf(str, max_size, "%f", digit) < 0) {
        return false;
    }

    // 1.00000 -> 1.
    char *head_zero = str;
    while ((head_zero = strchr(head_zero, '0')) != NULL) {
        char *non_zero_pos = strchr_not(head_zero, '0');
        if (non_zero_pos == NULL) {
            *head_zero = '\0';
            break;
        }
        else if (non_zero_pos[1] == '\0') {    // last is non zero
            break;
        }
        else {
            head_zero = non_zero_pos + 1;
        }
    }
    // 1. -> 1
    char *last_pos;
    if ((last_pos = last_chr(str)) != NULL && *last_pos == '.') {
        *last_pos = '\0';
    }
    return true;
}

なぜか必要とも思えない関数ばかりにコメントが。
文法とかいつも通り気にしてない。あばばば

/*
 * Return pointer to first character which is NOT c of str.
 * Return NULL if all characters are c or strlen(str) == 0.
 */
char*
strchr_not(const char *str, int c)
{
    for (; *str; str++)
        if (*str != c)
            return (char*)str;
    return NULL;
}
/*
 * Return pointer to last character of str.
 * Return NULL if strlen(str) == 0.
 */
char*
last_chr(const char *str)
{
    for (; *str; str++)
        if (str[1] == '\0')
            return (char*)str;
    return NULL;
}