Updated uses of varargs in the library to C style.
This commit is contained in:
Родитель
7977da0830
Коммит
d689bcc095
158
src/library.js
158
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',
|
||||
|
|
Загрузка…
Ссылка в новой задаче