Sunday, October 14, 2012

All Platform Parser Issues Resolved

On the Windows platform, the C format specifier "%g" outputs three digits in the exponent always whereas on Linux, only two digits output unless three are needed.  Looking at the C99 standard, it says basically "at least two exponent digits" should be output, so with that criteria, Windows is acceptable.  It also appears that Microsoft decided that three exponent digits should always be output, and the GNU compiler suite decided to follow this on Windows.  There is no way to control the number of exponent digits in the "%g" specifier.

The parser print token routine was modified to output two exponent digits if the first one is zero.  This was accomplished by first outputting the number into a temporary character buffer using the "%g" specifier.  Then it searches for an 'e' character in the string.  If the fourth character from the 'e' is not a zero-terminator, then that means there are three exponent digits.  If the second character from the 'e' is a '0' then the last two digits is moved on top of this zero.

Hit the Continue... for a code snippet of the solution.  This change will now output two exponent digits always if the first one is zero.  This code will do nothing on the Linux platform.  The expected results for parser test #3 were updated for two exponent digits were applicable (five instances).

Since the major CMake issues have been resolved and the 0.1.16 release will be about the build system, the cmake0.1.16 branch was merged to branch0.1.16 branch.  This last commit was also tagged as v0.1.16‑pre‑1.  On GitHub, a zip (or .tar.gz) files can be downloaded directly for a tag, which contain all the files at that tag, so it is not necessary to install git to retrieve the files.  This file does not contain the git repository however.  There are still a few more build issues to take care of.

Below is the code snippet on how force two exponent digits to be output with the "%g" format specifier when the first of three exponent digits is a zero.
char bfr[20];
char *exp;
double value;

sprintf(bfr, "%g", value);
exp = strchr(bfr, 'e');
if (exp != NULL)  // contains an exponent?
{
    // 3 digits and first '0'?
    if (exp[4] != '\0' && exp[2] == '0')
    {
        // move last 2 digits over first '0'
        strcpy(exp + 2, exp + 3);
    }
}
printf("%s", bfr);
First the double value is output to a temporary buffer using the sprintf() function with the "%g" specifier.  Consider the two possible resulting buffers on each platform, Linux with two exponents digits and Windows with three (the '@' represents the zero-terminator):
bfr[]    0 1 2 3 4 5 6 7 8 9
Linux:   1 . 2 3 e + 3 8 @
Windows: 1 . 2 3 e + 0 3 8 @
exp[]            0 1 2 3 4 5
The strchr() function is used to find the 'e' character and sets the exp pointer to it.  If there is no 'e' character (the pointer is null), then there is no exponent and the buffer is output without modification using the "%s" string specifier.  The exp pointer is used as an array with an 'e' at first [0] element, the sign at the second [1] element, etc.

If there is an 'e' character, then a check is made if the [4] array element is a zero-terminator.  This indicates that there are only two exponent digits.  If there are three exponent digits, then if the [2] element (the first exponent digit) is a '0' character, then the strcpy() function is used to move the last two exponent digits (and zero-terminator) on top of the first exponent '0' digit.  The modified buffer is then output.

No comments:

Post a Comment

All comments and feedback welcomed, whether positive or negative.
(Anonymous comments are allowed, but comments with URL links or unrelated comments will be removed.)