diff options
-rw-r--r-- | src/library.js | 158 |
1 files changed, 54 insertions, 104 deletions
diff --git a/src/library.js b/src/library.js index e6ca3851..c13e2ba0 100644 --- a/src/library.js +++ b/src/library.js @@ -854,12 +854,14 @@ LibraryManager.library = { __flock_struct_layout: Runtime.generateStructInfo(null, '%struct.flock'), open__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', '__dirent_struct_layout'], - open: function(path, oflag, mode) { + open: function(path, oflag, varargs) { // int open(const char *path, int oflag, ...); // http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html // NOTE: This implementation tries to mimic glibc rather that strictly // following the POSIX standard. + var mode = {{{ makeGetValue('varargs', 0, 'i32') }}}; + // Simplify flags. var accessMode = oflag & 0x3; // O_ACCMODE. var isWrite = accessMode != 0x0; // O_RDONLY. @@ -958,10 +960,12 @@ LibraryManager.library = { creat: function(path, mode) { // int creat(const char *path, mode_t mode); // http://pubs.opengroup.org/onlinepubs/009695399/functions/creat.html - return _open(path, 0x241, mode); // O_WRONLY | O_CREAT | O_TRUNC. + var modePtr = allocate([mode, 0, 0, 0], 'i32', ALLOC_STACK); + var ret = _open(path, 0x241, modePtr); // O_WRONLY | O_CREAT | O_TRUNC. + return ret; }, fcntl__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', '__flock_struct_layout'], - fcntl: function(fildes, cmd, arg) { + fcntl: function(fildes, cmd, varargs) { // int fcntl(int fildes, int cmd, ...); // http://pubs.opengroup.org/onlinepubs/009695399/functions/fcntl.html if (!(fildes in FS.streams)) { @@ -971,6 +975,7 @@ LibraryManager.library = { var stream = FS.streams[fildes]; switch (cmd) { case 0: // F_DUPFD. + var arg = {{{ makeGetValue('varargs', 0, 'i32') }}}; if (arg < 0) { ___setErrNo(ERRNO_CODES.EINVAL); return -1; @@ -994,10 +999,12 @@ LibraryManager.library = { // Synchronization and blocking flags are irrelevant to us. return flags; case 4: // F_SETFL. + var arg = {{{ makeGetValue('varargs', 0, 'i32') }}}; stream.isAppend = Boolean(arg | 0x400); // O_APPEND. // Synchronization and blocking flags are irrelevant to us. return 0; case 5: // F_GETLK. + var arg = {{{ makeGetValue('varargs', 0, 'i32') }}}; var offset = ___flock_struct_layout.l_type; // We're always unlocked. {{{ makeSetValue('arg', 'offset', '2', 'i16') }}} // F_UNLCK. @@ -1147,7 +1154,9 @@ LibraryManager.library = { dup: function(fildes) { // int dup(int fildes); // http://pubs.opengroup.org/onlinepubs/000095399/functions/dup.html - return _fcntl(fildes, 0, 0); // F_DUPFD. + var fildes2Ptr = allocate([0, 0, 0, 0], 'i32', ALLOC_STACK); + var ret = _fcntl(fildes, 0, fildes2Ptr); // F_DUPFD. + return ret; }, dup2__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'fcntl', 'close'], dup2: function(fildes, fildes2) { @@ -1160,7 +1169,9 @@ LibraryManager.library = { return fildes; } else { _close(fildes2); - return _fcntl(fildes, 0, fildes2); // F_DUPFD. + var fildes2Ptr = allocate([fildes2, 0, 0, 0], 'i32', ALLOC_STACK); + var ret = _fcntl(fildes, 0, fildes2Ptr); // F_DUPFD. + return ret } }, fchown__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', 'chown'], @@ -2121,13 +2132,14 @@ LibraryManager.library = { // ========================================================================== // TODO: Document. - _scanString: function(format, get, unget, args) { + _scanString: function(format, get, unget, varargs) { // Supports %x, %4x, %d.%d, %s. // TODO: Support all format specifiers. format = Pointer_stringify(format); var formatIndex = 0; var argsi = 0; var fields = 0; + var argIndex = 0; for (var formatIndex = 0; formatIndex < format.length; formatIndex++) { var next = get(); if (next <= 0) return fields; // End of input. @@ -2161,18 +2173,19 @@ LibraryManager.library = { } if (buffer.length === 0) return 0; // Failure. var text = buffer.join(''); + var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}}; + argIndex += Runtime.getNativeFieldSize('void*'); switch (type) { case 'd': - {{{ makeSetValue('args.shift()', '0', 'parseInt(text, 10)', 'i32') }}} + {{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i32') }}} break; case 'x': - {{{ makeSetValue('args.shift()', '0', 'parseInt(text, 16)', 'i32') }}} + {{{ makeSetValue('argPtr', 0, 'parseInt(text, 16)', 'i32') }}} break; case 's': var array = intArrayFromString(text); - var buf = args.shift(); for (var j = 0; j < array.length; j++) { - {{{ makeSetValue('buf', 'j', 'array[j]', 'i8') }}} + {{{ makeSetValue('argPtr', 'j', 'array[j]', 'i8') }}} } break; } @@ -2188,44 +2201,19 @@ LibraryManager.library = { return fields; }, // Performs prtinf-style formatting. - // isVarArgs: Whether the arguments are passed in varargs style, i.e. the - // third parameter is an address of the start of the argument list. // 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(isVarArgs, format/*, ...*/) { + _formatString: function(format, varargs) { var textIndex = format; var argIndex = 0; - var getNextArg; - if (isVarArgs) { - var varArgStart = arguments[2]; - getNextArg = function(type) { - var ret; - if (type === 'double') { - ret = {{{ makeGetValue('varArgStart', 'argIndex', 'double') }}}; - } else if (type === 'float') { - ret = {{{ makeGetValue('varArgStart', 'argIndex', 'float') }}}; - } else if (type === 'i64') { - ret = {{{ makeGetValue('varArgStart', 'argIndex', 'i64') }}}; - } else if (type === 'i32') { - ret = {{{ makeGetValue('varArgStart', 'argIndex', 'i32') }}}; - } else if (type === 'i16') { - ret = {{{ makeGetValue('varArgStart', 'argIndex', 'i16') }}}; - } else if (type === 'i8') { - ret = {{{ makeGetValue('varArgStart', 'argIndex', 'i8') }}}; - } else if (type[type.length - 1] === '*') { - ret = {{{ makeGetValue('varArgStart', 'argIndex', 'void*') }}}; - } else { - throw new Error('Unknown formatString argument type: ' + type); - } - argIndex += Runtime.getNativeFieldSize(type); - return Number(ret); - }; - } else { - var args = arguments; - getNextArg = function() { - return Number(args[2 + argIndex++]); - }; - } + var getNextArg = function(type) { + // NOTE: Explicitly ignoring type safety. Otherwise this fails: + // int x = 4; printf("%c\n", (char)x); + var ret = {{{ makeGetValue('varargs', 'argIndex', 'null', undefined, undefined, true) }}}; + argIndex += Runtime.getNativeFieldSize(type); + return Number(ret); + }; var ret = []; var curr, next, currArg; @@ -2748,7 +2736,8 @@ LibraryManager.library = { ___setErrNo(ERRNO_CODES.EINVAL); return 0; } - var ret = _open(filename, flags, 0x1FF); // All creation permissions. + var modePtr = allocate([0x1FF, 0, 0, 0], 'i32', ALLOC_STACK) // All creation permissions. + var ret = _open(filename, flags, modePtr); return (ret == -1) ? 0 : ret; }, fputc__deps: ['$FS', 'write'], @@ -3035,43 +3024,38 @@ LibraryManager.library = { }, fscanf__deps: ['$FS', '__setErrNo', '$ERRNO_CODES', '_scanString', 'getc', 'ungetc'], - fscanf: function(stream, format/*, ...*/) { + fscanf: function(stream, format, varargs) { // int fscanf(FILE *restrict stream, const char *restrict format, ... ); // http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html if (stream in FS.streams) { - var args = Array.prototype.slice.call(arguments, 2); var get = function() { return _fgetc(stream); }; var unget = function(c) { return _ungetc(c, stream); }; - return __scanString(format, get, unget, args); + return __scanString(format, get, unget, varargs); } else { return -1; } }, scanf__deps: ['fscanf'], - scanf: function(format/*, ...*/) { + scanf: function(format, varargs) { // int scanf(const char *restrict format, ... ); // http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html - var args = Array.prototype.slice.call(arguments, 0); - args.unshift({{{ makeGetValue('_stdin', '0', 'void*') }}}); - return _fscanf.apply(null, args); + var stdin = {{{ makeGetValue('_stdin', '0', 'void*') }}}; + return _fscanf(stdin, format, varargs); }, sscanf__deps: ['_scanString'], - sscanf: function(s, format/*, ...*/) { + sscanf: function(s, format, varargs) { // int sscanf(const char *restrict s, const char *restrict format, ... ); // http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html var index = 0; var get = function() { return {{{ makeGetValue('s', 'index++', 'i8') }}}; }; var unget = function() { index--; }; - var args = Array.prototype.slice.call(arguments, 2); - return __scanString(format, get, unget, args); + return __scanString(format, get, unget, varargs); }, snprintf__deps: ['_formatString'], - snprintf: function(s, n, format/*, ... */) { + snprintf: function(s, n, format, varargs) { // int snprintf(char *restrict s, size_t n, const char *restrict format, ...); // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html - var args = Array.prototype.slice.call(arguments, 2); - args.unshift(false); - var result = __formatString.apply(null, args); + var result = __formatString(format, varargs); var limit = (n === undefined) ? result.length : Math.min(result.length, n - 1); for (var i = 0; i < limit; i++) { @@ -3081,65 +3065,31 @@ LibraryManager.library = { return result.length; }, fprintf__deps: ['fwrite', '_formatString'], - fprintf: function(stream, format/*, ... */) { + fprintf: function(stream, format, varargs) { // int fprintf(FILE *restrict stream, const char *restrict format, ...); // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html - var args = Array.prototype.slice.call(arguments, 1); - args.unshift(false); - var result = __formatString.apply(null, args); + var result = __formatString(format, varargs); var buffer = allocate(result, 'i8', ALLOC_STACK); var ret = _fwrite(buffer, 1, result.length, stream); return ret; }, printf__deps: ['fprintf'], - printf: function(format/*, ... */) { + printf: function(format, varargs) { // int printf(const char *restrict format, ...); // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html - var args = Array.prototype.slice.call(arguments, 0); - args.unshift({{{ makeGetValue('_stdout', '0', 'void*') }}}); - return _fprintf.apply(null, args); + var stdout = {{{ makeGetValue('_stdout', '0', 'void*') }}}; + return _fprintf(stdout, format, varargs); }, sprintf__deps: ['snprintf'], - sprintf: function(s, format/*, ... */) { + sprintf: function(s, format, varargs) { // int sprintf(char *restrict s, const char *restrict format, ...); // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html - var args = [s, undefined].concat(Array.prototype.slice.call(arguments, 1)); - return _snprintf.apply(null, args); - }, - vfprintf__deps: ['fwrite', '_formatString'], - vfprintf: function(stream, format, ap) { - // int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap); - // http://pubs.opengroup.org/onlinepubs/000095399/functions/vprintf.html - var result = __formatString(true, format, ap); - var buffer = allocate(result, 'i8', ALLOC_STACK); - var ret = _fwrite(buffer, 1, result.length, stream); - return ret; - }, - vsnprintf__deps: ['_formatString'], - vsnprintf: function(s, n, format, ap) { - // int vsnprintf(char *restrict s, size_t n, const char *restrict format, va_list ap); - // http://pubs.opengroup.org/onlinepubs/000095399/functions/vprintf.html - var result = __formatString(true, format, ap); - var limit = (n === undefined) ? result.length - : Math.min(result.length, n - 1); - for (var i = 0; i < limit; i++) { - {{{ makeSetValue('s', 'i', 'result[i]', 'i8') }}}; - } - {{{ makeSetValue('s', 'i', '0', 'i8') }}}; - return result.length; - }, - vprintf__deps: ['vfprintf'], - vprintf: function(format, ap) { - // int vprintf(const char *restrict format, va_list ap); - // http://pubs.opengroup.org/onlinepubs/000095399/functions/vprintf.html - return _vfprintf({{{ makeGetValue('_stdout', '0', 'void*') }}}, format, ap); - }, - vsprintf__deps: ['vsnprintf'], - vsprintf: function(s, format, ap) { - // int vsprintf(char *restrict s, const char *restrict format, va_list ap); - // http://pubs.opengroup.org/onlinepubs/000095399/functions/vprintf.html - return _vsnprintf(s, undefined, format, ap); + return _snprintf(s, undefined, format, varargs); }, + vfprintf: 'fprintf', + vsnprintf: 'snprintf', + vprintf: 'printf', + vsprintf: 'sprintf', // TODO: Implement v*scanf(). __01fopen64_: 'fopen', __01fseeko64_: 'fseek', |