Skip to content

Instantly share code, notes, and snippets.

@kripken
Created November 19, 2012 20:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kripken/4113842 to your computer and use it in GitHub Desktop.
Save kripken/4113842 to your computer and use it in GitHub Desktop.
sscanf fix
diff --git a/src/library.js b/src/library.js
index eb4aad4..b109263 100644
--- a/src/library.js
+++ b/src/library.js
@@ -2452,30 +2452,25 @@ LibraryManager.library = {
}
}
var formatIndex = 0;
var argsi = 0;
var fields = 0;
var argIndex = 0;
var next;
- next = 1;
mainLoop:
- for (var formatIndex = 0; formatIndex < format.length; formatIndex++) {
+ for (var formatIndex = 0; formatIndex < format.length;) {
// remove whitespace
while (1) {
next = get();
if (next == 0) return fields;
if (!(next in __scanString.whiteSpace)) break;
- }
- unget(next);
-
- if (next <= 0) return fields;
- var next = get();
- if (next <= 0) return fields; // End of input.
+ }
+ unget();
if (format[formatIndex] === '%') {
formatIndex++;
var maxSpecifierStart = formatIndex;
while (format[formatIndex].charCodeAt(0) >= '0'.charCodeAt(0) &&
format[formatIndex].charCodeAt(0) <= '9'.charCodeAt(0)) {
formatIndex++;
}
@@ -2510,39 +2505,41 @@ LibraryManager.library = {
last = buffer.length;
}
next = get();
}
unget(next);
while (buffer.length > last) {
unget(buffer.pop().charCodeAt(0));
}
- next = get();
} else if (type != 'n') {
+ next = get();
var first = true;
while ((curr < max_ || isNaN(max_)) && next > 0) {
if (!(next in __scanString.whiteSpace) && // stop on whitespace
(type == 's' ||
((type === 'd' || type == 'u' || type == 'i') && ((next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) ||
(first && next == '-'.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)))) &&
(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++;
+ first = false;
} else {
break;
}
- first = false;
}
+ unget();
}
if (buffer.length === 0 && type != 'n') return 0; // Failure.
var text = buffer.join('');
+Module.print('scann ' + [type, text, String.fromCharCode(get()), unget(), format[formatIndex]]);
var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}};
argIndex += Runtime.getNativeFieldSize('void*');
switch (type) {
case 'd': case 'u': case 'i':
if (half) {
{{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i16') }}};
} else if(longLong) {
{{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i64') }}};
@@ -2562,39 +2559,43 @@ LibraryManager.library = {
break;
case 's':
var array = intArrayFromString(text);
for (var j = 0; j < array.length; j++) {
{{{ makeSetValue('argPtr', 'j', 'array[j]', 'i8') }}}
}
break;
case 'n':
- {{{ makeSetValue('argPtr', 0, 'soFar-1', 'i32') }}}
+ {{{ makeSetValue('argPtr', 0, 'soFar', 'i32') }}}
break;
}
if (type != 'n') fields++;
if (next <= 0) break mainLoop; // End of input.
+//Module.print('fi ' + formatIndex);
} else if (format[formatIndex] in __scanString.whiteSpace) {
while (next in __scanString.whiteSpace) {
next = get();
if (next <= 0) break mainLoop; // End of input.
}
unget(next);
+ formatIndex++;
} else {
// Not a specifier.
+//Module.print('zz see ' + format[formatIndex] + ' ? ' + String.fromCharCode(next));
if (format[formatIndex].charCodeAt(0) !== next) {
unget(next);
break mainLoop;
}
+ formatIndex++;
}
}
// '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') }}}
+ {{{ makeSetValue('argPtr', 0, 'soFar', 'i32') }}}
}
return fields;
},
// Performs prtinf-style formatting.
// format: A pointer to the format string.
// varargs: A pointer to the start of the arguments list.
// Returns the resulting string string as a character array.
_formatString: function(format, varargs) {
diff --git a/src/postamble.js b/src/postamble.js
index 144b5af..ec1db66 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -1,11 +1,17 @@
// === Auto-generated postamble setup entry stuff ===
+if (typeof _Program_Main_string__ == 'function') {
+ var _main = Module['_main'] = function() {
+ Module.print('called compiled code, returning ' + _Program_Main_string__());
+ }
+}
+
Module.callMain = function callMain(args) {
var argc = args.length+1;
function pad() {
for (var i = 0; i < {{{ QUANTUM_SIZE }}}-1; i++) {
argv.push(0);
}
}
var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_STATIC) ];
diff --git a/tests/runner.py b/tests/runner.py
index 5896f48..bea617d 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -4537,17 +4537,32 @@ Pass: 0.000012 0.000012''')
printf("%lld,%lld,%lld\n", negS, negM, negL);
return 0;
}
'''
self.do_run(src, '3\n123,1073741823,1125899906842620\n' +
'3\n-123,-1073741823,-1125899906842620\n')
-
+
+ def test_sscanf_4(self):
+ src = r'''
+ #include <stdio.h>
+
+ int main()
+ {
+ char pYear[16], pMonth[16], pDay[16], pDate[64];
+ printf("%d\n", sscanf("Nov 19 2012", "%s%s%s", pMonth, pDay, pYear));
+ printf("day %s, month %s, year %s \n", pDay, pMonth, pYear);
+ return(0);
+ }
+ '''
+
+ self.do_run(src, '3\nday 19, month Nov, year 2012');
+
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()
self.do_run(src, expected, extra_emscripten_args=['-H', 'libc/langinfo.h'])
def test_files(self):
if self.emcc_args is not None and '-O2' in self.emcc_args:
self.emcc_args += ['--closure', '1'] # Use closure here, to test we don't break FS stuff
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment