aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-10-26 11:22:29 -0700
committerAlon Zakai <alonzakai@gmail.com>2012-10-26 11:22:29 -0700
commitadbebc446efce391c83bc3f947bc086bb89207cd (patch)
tree7c4af98003c1318fe98d09762cc5be4922e6b234
parent60b7e38828c12c872a6b9daa90564df70dbaa2f6 (diff)
support for %n in sscanf
-rw-r--r--src/library.js33
-rwxr-xr-xtests/runner.py20
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()