diff options
-rw-r--r-- | src/library.js | 64 | ||||
-rw-r--r-- | tests/runner.py | 86 |
2 files changed, 97 insertions, 53 deletions
diff --git a/src/library.js b/src/library.js index 1971ab66..1534dc7e 100644 --- a/src/library.js +++ b/src/library.js @@ -2132,9 +2132,14 @@ LibraryManager.library = { // stdio.h // ========================================================================== + _isFloat: function(text) { + return !!(/^[+]?[0-9]*\.?[0-9]+([eE][+-]?[0-9]+)?$/.exec(text)); + }, + // TODO: Document. + _scanString__deps: ['_isFloat'], _scanString: function(format, get, unget, varargs) { - // Supports %x, %4x, %d.%d, %s. + // Supports %x, %4x, %d.%d, %s, %f, %lf. // TODO: Support all format specifiers. format = Pointer_stringify(format); var formatIndex = 0; @@ -2157,22 +2162,43 @@ LibraryManager.library = { max_ = parseInt(format.slice(maxSpecifierStart, formatIndex), 10); } // TODO: Handle type size modifier. + var long_ = false; + if (format[formatIndex] == 'l') { + long_ = true; + formatIndex++; + } var type = format[formatIndex]; formatIndex++; var curr = 0; var buffer = []; - while ((curr < max_ || isNaN(max_)) && next > 0) { - if ((type === 'd' && next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) || - (type === 'x' && (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0) || - next >= 'a'.charCodeAt(0) && next <= 'f'.charCodeAt(0) || - next >= 'A'.charCodeAt(0) && next <= 'F'.charCodeAt(0))) || - (type === 's') && - (formatIndex >= format.length || next !== format[formatIndex].charCodeAt(0))) { // Stop when we read something that is coming up + // Read characters according to the format. floats are trickier, they may be in an unfloat state in the middle, then be a valid float later + if (type == 'f') { + var last = -1; + while (next > 0) { buffer.push(String.fromCharCode(next)); + if (__isFloat(buffer.join(''))) { + last = buffer.length; + } next = get(); - curr++; - } else { - break; + } + while (buffer.length > last) { + buffer.pop(); + unget(); + } + } else { + while ((curr < max_ || isNaN(max_)) && next > 0) { + if ((type === 'd' && next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) || + (type === 'x' && (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0) || + next >= 'a'.charCodeAt(0) && next <= 'f'.charCodeAt(0) || + next >= 'A'.charCodeAt(0) && next <= 'F'.charCodeAt(0))) || + (type === 's') && + (formatIndex >= format.length || next !== format[formatIndex].charCodeAt(0))) { // Stop when we read something that is coming up + buffer.push(String.fromCharCode(next)); + next = get(); + curr++; + } else { + break; + } } } if (buffer.length === 0) return 0; // Failure. @@ -2186,6 +2212,13 @@ LibraryManager.library = { case 'x': {{{ makeSetValue('argPtr', 0, 'parseInt(text, 16)', 'i32') }}} break; + case 'f': + if (long_) { + {{{ makeSetValue('argPtr', 0, 'parseFloat(text)', 'double') }}} + } else { + {{{ makeSetValue('argPtr', 0, 'parseFloat(text)', 'float') }}} + } + break; case 's': var array = intArrayFromString(text); for (var j = 0; j < array.length; j++) { @@ -2215,7 +2248,7 @@ LibraryManager.library = { // NOTE: Explicitly ignoring type safety. Otherwise this fails: // int x = 4; printf("%c\n", (char)x); var ret; - if (type === 'float' || type === 'double') { + if (type === 'double') { ret = {{{ makeGetValue('varargs', 'argIndex', 'double', undefined, undefined, true) }}}; #if I64_MODE == 1 } else if (type == 'i64') { @@ -2224,6 +2257,7 @@ LibraryManager.library = { ret = unSign(ret[0], 32) + unSign(ret[1], 32)*Math.pow(2, 32); // Unsigned in this notation. Signed later if needed. // XXX - loss of precision #endif } else { + type = 'i32'; // varargs are always i32, i64, or double ret = {{{ makeGetValue('varargs', 'argIndex', 'i32', undefined, undefined, true) }}}; } argIndex += Runtime.getNativeFieldSize(type); @@ -2313,9 +2347,9 @@ LibraryManager.library = { var nextNext = {{{ makeGetValue(0, 'textIndex+2', 'i8') }}}; if (nextNext == 'h'.charCodeAt(0)) { textIndex++; - argSize = 1; // char + argSize = 1; // char (actually i32 in varargs) } else { - argSize = 2; // short + argSize = 2; // short (actually i32 in varargs) } break; case 'l': @@ -2427,7 +2461,7 @@ LibraryManager.library = { }); } else if (['f', 'F', 'e', 'E', 'g', 'G'].indexOf(String.fromCharCode(next)) != -1) { // Float. - var currArg = getNextArg(argSize === 4 ? 'float' : 'double'); + var currArg = getNextArg('double'); var argText; if (isNaN(currArg)) { diff --git a/tests/runner.py b/tests/runner.py index 7d5a9580..74fb5057 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -3007,45 +3007,55 @@ at function.:blag self.do_run(src) # Part 2: doubles (issue 148) - return # TODO: Make the second part here work - src = r''' - #include <stdio.h> + if Settings.USE_TYPED_ARRAYS == 2: + for ftype in ['float', 'double']: + src = r''' + #include <stdio.h> - int main(){ - char strval1[] = "1.2345678901"; - char strval2[] = "1.23456789e5"; - char strval3[] = "1.23456789E5"; - char strval4[] = "1.2345678e-5"; - char strval5[] = "1.2345678E-5"; - double dblval = 1.2345678901; - double tstval; - - sscanf(strval1, "%lf", &tstval); - if(dblval != tstval) printf("FAIL: Values are not equal: %lf %lf\n", dblval, tstval); - else printf("Pass: %lf %lf\n", tstval, dblval); - - sscanf(strval2, "%lf", &tstval); - dblval = 123456.789; - if(dblval != tstval) printf("FAIL: Values are not equal: %lf %lf\n", dblval, tstval); - else printf("Pass: %lf %lf\n", tstval, dblval); - - sscanf(strval3, "%lf", &tstval); - dblval = 123456.789; - if(dblval != tstval) printf("FAIL: Values are not equal: %lf %lf\n", dblval, tstval); - else printf("Pass: %lf %lf\n", tstval, dblval); - - sscanf(strval4, "%lf", &tstval); - dblval = 0.000012345678; - if(dblval != tstval) printf("FAIL: Values are not equal: %lf %lf\n", dblval, tstval); - else printf("Pass: %lf %lf\n", tstval, dblval); - - sscanf(strval5, "%lf", &tstval); - dblval = 0.000012345678; - if(dblval != tstval) printf("FAIL: Values are not equal: %lf %lf\n", dblval, tstval); - else printf("Pass: %lf %lf\n", tstval, dblval); - } - ''' - self.do_run(src) + int main(){ + char strval1[] = "1.2345678901"; + char strval2[] = "1.23456789e5"; + char strval3[] = "1.23456789E5"; + char strval4[] = "1.2345678e-5"; + char strval5[] = "1.2345678E-5"; + double dblval = 1.2345678901; + double tstval; + + sscanf(strval1, "%lf", &tstval); + if(dblval != tstval) printf("FAIL: Values are not equal: %lf %lf\n", dblval, tstval); + else printf("Pass: %lf %lf\n", tstval, dblval); + + sscanf(strval2, "%lf", &tstval); + dblval = 123456.789; + if(dblval != tstval) printf("FAIL: Values are not equal: %lf %lf\n", dblval, tstval); + else printf("Pass: %lf %lf\n", tstval, dblval); + + sscanf(strval3, "%lf", &tstval); + dblval = 123456.789; + if(dblval != tstval) printf("FAIL: Values are not equal: %lf %lf\n", dblval, tstval); + else printf("Pass: %lf %lf\n", tstval, dblval); + + sscanf(strval4, "%lf", &tstval); + dblval = 0.000012345678; + if(dblval != tstval) printf("FAIL: Values are not equal: %lf %lf\n", dblval, tstval); + else printf("Pass: %lf %lf\n", tstval, dblval); + + sscanf(strval5, "%lf", &tstval); + dblval = 0.000012345678; + if(dblval != tstval) printf("FAIL: Values are not equal: %lf %lf\n", dblval, tstval); + else printf("Pass: %lf %lf\n", tstval, dblval); + + return 0; + } + ''' + if ftype == 'float': + self.do_run(src.replace('%lf', '%f').replace('double', 'float'), '''Pass: 1.234568 1.234568 +Pass: 123456.789063 123456.789063 +Pass: 123456.789063 123456.789063 +Pass: 0.000012 0.000012 +Pass: 0.000012 0.000012''') + else: + self.do_run(src) def test_langinfo(self): src = open(path_from_root('tests', 'langinfo', 'test.c'), 'r').read() |