diff options
Diffstat (limited to 'src/library.js')
-rw-r--r-- | src/library.js | 158 |
1 files changed, 122 insertions, 36 deletions
diff --git a/src/library.js b/src/library.js index 7a144951..abee70c4 100644 --- a/src/library.js +++ b/src/library.js @@ -628,24 +628,13 @@ LibraryManager.library = { // http://pubs.opengroup.org/onlinepubs/000095399/functions/chdir.html // NOTE: The path argument may be a string, to simplify fchdir(). if (typeof path !== 'string') path = Pointer_stringify(path); - var lookup; try { - lookup = FS.lookupPath(path, { follow: true }); + FS.chdir(path); + return 0; } catch (e) { FS.handleFSError(e); return -1; } - if (!FS.isDir(lookup.node.mode)) { - ___setErrNo(ERRNO_CODES.ENOTDIR); - return -1; - } - var err = FS.nodePermissions(lookup.node, 'x'); - if (err) { - ___setErrNo(err); - return -1; - } - FS.currentPath = lookup.path; - return 0; }, chown__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], chown: function(path, owner, group, dontResolveLastLink) { @@ -849,12 +838,14 @@ LibraryManager.library = { if (size == 0) { ___setErrNo(ERRNO_CODES.EINVAL); return 0; - } else if (size < FS.currentPath.length + 1) { + } + var cwd = FS.cwd(); + if (size < cwd.length + 1) { ___setErrNo(ERRNO_CODES.ERANGE); return 0; } else { - for (var i = 0; i < FS.currentPath.length; i++) { - {{{ makeSetValue('buf', 'i', 'FS.currentPath.charCodeAt(i)', 'i8') }}} + for (var i = 0; i < cwd.length; i++) { + {{{ makeSetValue('buf', 'i', 'cwd.charCodeAt(i)', 'i8') }}} } {{{ makeSetValue('buf', 'i', '0', 'i8') }}} return buf; @@ -1600,12 +1591,6 @@ LibraryManager.library = { __scanString.whiteSpace[{{{ charCode('\v') }}}] = 1; __scanString.whiteSpace[{{{ charCode('\f') }}}] = 1; __scanString.whiteSpace[{{{ charCode('\r') }}}] = 1; - __scanString.whiteSpace[' '] = 1; - __scanString.whiteSpace['\t'] = 1; - __scanString.whiteSpace['\n'] = 1; - __scanString.whiteSpace['\v'] = 1; - __scanString.whiteSpace['\f'] = 1; - __scanString.whiteSpace['\r'] = 1; } // Supports %x, %4x, %d.%d, %lld, %s, %f, %lf. // TODO: Support all format specifiers. @@ -1645,7 +1630,7 @@ LibraryManager.library = { if (nextC > 0) { var maxx = 1; if (nextC > formatIndex+1) { - var sub = format.substring(formatIndex+1, nextC) + var sub = format.substring(formatIndex+1, nextC); maxx = parseInt(sub); if (maxx != sub) maxx = 0; } @@ -1663,6 +1648,53 @@ LibraryManager.library = { } } + // handle %[...] + if (format[formatIndex] === '%' && format.indexOf('[', formatIndex+1) > 0) { + var match = /\%([0-9]*)\[(\^)?(\]?[^\]]*)\]/.exec(format.substring(formatIndex)); + if (match) { + var maxNumCharacters = parseInt(match[1]) || Infinity; + var negateScanList = (match[2] === '^'); + var scanList = match[3]; + + // expand "middle" dashs into character sets + var middleDashMatch; + while ((middleDashMatch = /([^\-])\-([^\-])/.exec(scanList))) { + var rangeStartCharCode = middleDashMatch[1].charCodeAt(0); + var rangeEndCharCode = middleDashMatch[2].charCodeAt(0); + for (var expanded = ''; rangeStartCharCode <= rangeEndCharCode; expanded += String.fromCharCode(rangeStartCharCode++)); + scanList = scanList.replace(middleDashMatch[1] + '-' + middleDashMatch[2], expanded); + } + + var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}}; + argIndex += Runtime.getAlignSize('void*', null, true); + fields++; + + for (var i = 0; i < maxNumCharacters; i++) { + next = get(); + if (negateScanList) { + if (scanList.indexOf(String.fromCharCode(next)) < 0) { + {{{ makeSetValue('argPtr++', 0, 'next', 'i8') }}}; + } else { + unget(); + break; + } + } else { + if (scanList.indexOf(String.fromCharCode(next)) >= 0) { + {{{ makeSetValue('argPtr++', 0, 'next', 'i8') }}}; + } else { + unget(); + break; + } + } + } + + // write out null-terminating character + {{{ makeSetValue('argPtr++', 0, '0', 'i8') }}}; + formatIndex += match[0].length; + + continue; + } + } // remove whitespace while (1) { next = get(); @@ -1724,6 +1756,17 @@ LibraryManager.library = { } else { next = get(); var first = true; + + // Strip the optional 0x prefix for %x. + if ((type == 'x' || type == 'X') && (next == {{{ charCode('0') }}})) { + var peek = get(); + if (peek == {{{ charCode('x') }}} || peek == {{{ charCode('X') }}}) { + next = get(); + } else { + unget(); + } + } + while ((curr < max_ || isNaN(max_)) && next > 0) { if (!(next in __scanString.whiteSpace) && // stop on whitespace (type == 's' || @@ -1785,7 +1828,7 @@ LibraryManager.library = { break; } fields++; - } else if (format[formatIndex] in __scanString.whiteSpace) { + } else if (format[formatIndex].charCodeAt(0) in __scanString.whiteSpace) { next = get(); while (next in __scanString.whiteSpace) { if (next <= 0) break mainLoop; // End of input. @@ -1856,6 +1899,7 @@ LibraryManager.library = { var flagLeftAlign = false; var flagAlternative = false; var flagZeroPad = false; + var flagPadSign = false; flagsLoop: while (1) { switch (next) { case {{{ charCode('+') }}}: @@ -1874,6 +1918,9 @@ LibraryManager.library = { flagZeroPad = true; break; } + case {{{ charCode(' ') }}}: + flagPadSign = true; + break; default: break flagsLoop; } @@ -2040,14 +2087,20 @@ LibraryManager.library = { } // Add sign if needed - if (flagAlwaysSigned) { - if (currArg < 0) { - prefix = '-' + prefix; - } else { + if (currArg >= 0) { + if (flagAlwaysSigned) { prefix = '+' + prefix; + } else if (flagPadSign) { + prefix = ' ' + prefix; } } + // Move sign to prefix so we zero-pad after the sign + if (argText.charAt(0) == '-') { + prefix = '-' + prefix; + argText = argText.substr(1); + } + // Add padding. while (prefix.length + argText.length < width) { if (flagLeftAlign) { @@ -2130,8 +2183,12 @@ LibraryManager.library = { if (next == {{{ charCode('E') }}}) argText = argText.toUpperCase(); // Add sign. - if (flagAlwaysSigned && currArg >= 0) { - argText = '+' + argText; + if (currArg >= 0) { + if (flagAlwaysSigned) { + argText = '+' + argText; + } else if (flagPadSign) { + argText = ' ' + argText; + } } } @@ -2769,6 +2826,13 @@ LibraryManager.library = { asprintf: function(s, format, varargs) { return _sprintf(-s, format, varargs); }, + dprintf__deps: ['_formatString', 'write'], + dprintf: function(fd, format, varargs) { + var result = __formatString(format, varargs); + var stack = Runtime.stackSave(); + var ret = _write(fd, allocate(result, 'i8', ALLOC_STACK), result.length); + Runtime.stackRestore(stack); + }, #if TARGET_X86 // va_arg is just like our varargs @@ -2777,6 +2841,7 @@ LibraryManager.library = { vprintf: 'printf', vsprintf: 'sprintf', vasprintf: 'asprintf', + vdprintf: 'dprintf', vscanf: 'scanf', vfscanf: 'fscanf', vsscanf: 'sscanf', @@ -2804,6 +2869,10 @@ LibraryManager.library = { vasprintf: function(s, format, va_arg) { return _asprintf(s, format, {{{ makeGetValue('va_arg', 0, '*') }}}); }, + vdprintf__deps: ['dprintf'], + vdprintf: function (fd, format, va_arg) { + return _dprintf(fd, format, {{{ makeGetValue('va_arg', 0, '*') }}}); + }, vscanf__deps: ['scanf'], vscanf: function(format, va_arg) { return _scanf(format, {{{ makeGetValue('va_arg', 0, '*') }}}); @@ -3674,6 +3743,7 @@ LibraryManager.library = { }, // We always assume ASCII locale. strcoll: 'strcmp', + strcoll_l: 'strcmp', strcasecmp__asm: true, strcasecmp__sig: 'iii', @@ -3940,6 +4010,7 @@ LibraryManager.library = { } }, _toupper: 'toupper', + toupper_l: 'toupper', tolower__asm: true, tolower__sig: 'ii', @@ -3950,54 +4021,65 @@ LibraryManager.library = { return (chr - {{{ charCode('A') }}} + {{{ charCode('a') }}})|0; }, _tolower: 'tolower', + tolower_l: 'tolower', // The following functions are defined as macros in glibc. islower: function(chr) { return chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}; }, + islower_l: 'islower', isupper: function(chr) { return chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}}; }, + isupper_l: 'isupper', isalpha: function(chr) { return (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) || (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}}); }, + isalpha_l: 'isalpha', isdigit: function(chr) { return chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}; }, - isdigit_l: 'isdigit', // no locale support yet + isdigit_l: 'isdigit', isxdigit: function(chr) { return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) || (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('f') }}}) || (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('F') }}}); }, - isxdigit_l: 'isxdigit', // no locale support yet + isxdigit_l: 'isxdigit', isalnum: function(chr) { return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) || (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) || (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}}); }, + isalnum_l: 'isalnum', ispunct: function(chr) { return (chr >= {{{ charCode('!') }}} && chr <= {{{ charCode('/') }}}) || (chr >= {{{ charCode(':') }}} && chr <= {{{ charCode('@') }}}) || (chr >= {{{ charCode('[') }}} && chr <= {{{ charCode('`') }}}) || (chr >= {{{ charCode('{') }}} && chr <= {{{ charCode('~') }}}); }, + ispunct_l: 'ispunct', isspace: function(chr) { return (chr == 32) || (chr >= 9 && chr <= 13); }, + isspace_l: 'isspace', isblank: function(chr) { return chr == {{{ charCode(' ') }}} || chr == {{{ charCode('\t') }}}; }, + isblank_l: 'isblank', iscntrl: function(chr) { return (0 <= chr && chr <= 0x1F) || chr === 0x7F; }, + iscntrl_l: 'iscntrl', isprint: function(chr) { return 0x1F < chr && chr < 0x7F; }, + isprint_l: 'isprint', isgraph: function(chr) { return 0x20 < chr && chr < 0x7F; }, + isgraph_l: 'isgraph', // Lookup tables for glibc ctype implementation. __ctype_b_loc: function() { // http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/baselib---ctype-b-loc.html @@ -4098,7 +4180,7 @@ LibraryManager.library = { llvm_va_end: function() {}, llvm_va_copy: function(ppdest, ppsrc) { - // copy the list start + // copy the list start {{{ makeCopyValues('ppdest', 'ppsrc', Runtime.QUANTUM_SIZE, 'null', null, 1) }}}; // copy the list's current offset (will be advanced with each call to va_arg) @@ -6270,11 +6352,15 @@ LibraryManager.library = { // locale.h // ========================================================================== + newlocale__deps: ['malloc'], newlocale: function(mask, locale, base) { - return 0; + return _malloc({{{ QUANTUM_SIZE}}}); }, - freelocale: function(locale) {}, + freelocale__deps: ['free'], + freelocale: function(locale) { + _free(locale); + }, uselocale: function(locale) { return 0; @@ -8619,7 +8705,7 @@ function autoAddDeps(object, name) { } // Add aborting stubs for various libc stuff needed by libc++ -['pthread_cond_signal', 'pthread_equal', 'wcstol', 'wcstoll', 'wcstoul', 'wcstoull', 'wcstof', 'wcstod', 'wcstold', 'swprintf', 'pthread_join', 'pthread_detach', 'strcoll_l', 'strxfrm_l', 'wcscoll_l', 'toupper_l', 'tolower_l', 'iswspace_l', 'iswprint_l', 'iswcntrl_l', 'iswupper_l', 'iswlower_l', 'iswalpha_l', 'iswdigit_l', 'iswpunct_l', 'iswxdigit_l', 'iswblank_l', 'wcsxfrm_l', 'towupper_l', 'towlower_l', 'catgets', 'catopen', 'catclose'].forEach(function(aborter) { +['pthread_cond_signal', 'pthread_equal', 'wcstol', 'wcstoll', 'wcstoul', 'wcstoull', 'wcstof', 'wcstod', 'wcstold', 'pthread_join', 'pthread_detach', 'catgets', 'catopen', 'catclose'].forEach(function(aborter) { LibraryManager.library[aborter] = function() { throw 'TODO: ' + aborter }; }); |