diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-10-26 11:22:29 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-10-26 11:22:29 -0700 |
commit | adbebc446efce391c83bc3f947bc086bb89207cd (patch) | |
tree | 7c4af98003c1318fe98d09762cc5be4922e6b234 | |
parent | 60b7e38828c12c872a6b9daa90564df70dbaa2f6 (diff) |
support for %n in sscanf
-rw-r--r-- | src/library.js | 33 | ||||
-rwxr-xr-x | tests/runner.py | 20 |
2 files changed, 48 insertions, 5 deletions
diff --git a/src/library.js b/src/library.js index 2855c33d..1164c81f 100644 --- a/src/library.js +++ b/src/library.js @@ -2437,6 +2437,20 @@ LibraryManager.library = { // Supports %x, %4x, %d.%d, %s, %f, %lf. // TODO: Support all format specifiers. format = Pointer_stringify(format); + var soFar = 0; + if (format.indexOf('%n') >= 0) { + // need to track soFar + var _get = get; + get = function() { + soFar++; + return _get(); + } + var _unget = unget; + unget = function() { + soFar--; + return _unget(); + } + } var formatIndex = 0; var argsi = 0; var fields = 0; @@ -2450,6 +2464,7 @@ LibraryManager.library = { } unget(next); next = 1; + mainLoop: for (var formatIndex = 0; formatIndex < format.length; formatIndex++) { if (next <= 0) return fields; var next = get(); @@ -2493,7 +2508,7 @@ LibraryManager.library = { unget(buffer.pop().charCodeAt(0)); } next = get(); - } else { + } else if (type != 'n') { var first = true; while ((curr < max_ || isNaN(max_)) && next > 0) { if (!(next in __scanString.whiteSpace) && // stop on whitespace @@ -2513,7 +2528,7 @@ LibraryManager.library = { first = false; } } - if (buffer.length === 0) return 0; // Failure. + if (buffer.length === 0 && type != 'n') return 0; // Failure. var text = buffer.join(''); var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}}; argIndex += Runtime.getNativeFieldSize('void*'); @@ -2541,22 +2556,30 @@ LibraryManager.library = { {{{ makeSetValue('argPtr', 'j', 'array[j]', 'i8') }}} } break; + case 'n': + {{{ makeSetValue('argPtr', 0, 'soFar-1', 'i32') }}} + break; } - fields++; + if (type != 'n') fields++; } else if (format[formatIndex] in __scanString.whiteSpace) { while (next in __scanString.whiteSpace) { next = get(); - if (next <= 0) return fields; // End of input. + if (next <= 0) break mainLoop; // End of input. } unget(next); } else { // Not a specifier. if (format[formatIndex].charCodeAt(0) !== next) { unget(next); - return fields; + break mainLoop; } } } + // 'n' is special in that it needs no input. so it can be at the end, even with nothing left to read + if (format[formatIndex-1] == '%' && format[formatIndex] == 'n') { + var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}}; + {{{ makeSetValue('argPtr', 0, 'soFar-1', 'i32') }}} + } return fields; }, // Performs prtinf-style formatting. diff --git a/tests/runner.py b/tests/runner.py index e3d5ac10..880e29a0 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -4341,6 +4341,26 @@ Pass: 123456.789000 123456.789000 Pass: 0.000012 0.000012 Pass: 0.000012 0.000012''') + def test_sscanf_n(self): + src = r''' + #include<stdio.h> + int main() { + char *line = "version 1.0"; + int i, l, lineno; + char word[80]; + if (sscanf(line, "%s%n", word, &l) != 1) { + printf("Header format error, line %d\n", lineno); + } + printf("[DEBUG] word 1: %s, l: %d\n", word, l); + + int x = sscanf("one %n two", "%s %n", word, &l); + printf("%d,%s,%d\n", x, word, l); + + return 0; + } + ''' + self.do_run(src, '''[DEBUG] word 1: version, l: 7\n1,one,4''') + def test_langinfo(self): src = open(path_from_root('tests', 'langinfo', 'test.c'), 'r').read() expected = open(path_from_root('tests', 'langinfo', 'output.txt'), 'r').read() |