mergeInto(LibraryManager.library, { $TTY__deps: ['$FS'], $TTY__postset: '__ATINIT__.unshift({ func: function() { TTY.init() } });' + '__ATEXIT__.push({ func: function() { TTY.shutdown() } });' + 'TTY.utf8 = new Runtime.UTF8Processor();', $TTY: { ttys: [], init: function () { // https://github.com/kripken/emscripten/pull/1555 // if (ENVIRONMENT_IS_NODE) { // // currently, FS.init does not distinguish if process.stdin is a file or TTY // // device, it always assumes it's a TTY device. because of this, we're forcing // // process.stdin to UTF8 encoding to at least make stdin reading compatible // // with text files until FS.init can be refactored. // process['stdin']['setEncoding']('utf8'); // } }, shutdown: function() { // https://github.com/kripken/emscripten/pull/1555 // if (ENVIRONMENT_IS_NODE) { // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)? // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists? // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call // process['stdin']['pause'](); // } }, register: function(dev, ops) { TTY.ttys[dev] = { input: [], output: [], ops: ops }; FS.registerDevice(dev, TTY.stream_ops); }, stream_ops: { open: function(stream) { var tty = TTY.ttys[stream.node.rdev]; if (!tty) { throw new FS.ErrnoError(ERRNO_CODES.ENODEV); } stream.tty = tty; stream.seekable = false; }, close: function(stream) { // flush any pending line data if (stream.tty.output.length) { stream.tty.ops.put_char(stream.tty, {{{ charCode('\n') }}}); } }, read: function(stream, buffer, offset, length, pos /* ignored */) { if (!stream.tty || !stream.tty.ops.get_char) { throw new FS.ErrnoError(ERRNO_CODES.ENXIO); } var bytesRead = 0; for (var i = 0; i < length; i++) { var result; try { result = stream.tty.ops.get_char(stream.tty); } catch (e) { throw new FS.ErrnoError(ERRNO_CODES.EIO); } if (result === undefined && bytesRead === 0) { throw new FS.ErrnoError(ERRNO_CODES.EAGAIN); } if (result === null || result === undefined) break; bytesRead++; buffer[offset+i] = result; } if (bytesRead) { stream.node.timestamp = Date.now(); } return bytesRead; }, write: function(stream, buffer, offset, length, pos) { if (!stream.tty || !stream.tty.ops.put_char) { throw new FS.ErrnoError(ERRNO_CODES.ENXIO); } for (var i = 0; i < length; i++) { try { stream.tty.ops.put_char(stream.tty, buffer[offset+i]); } catch (e) { throw new FS.ErrnoError(ERRNO_CODES.EIO); } } if (length) { stream.node.timestamp = Date.now(); } return i; } }, default_tty_ops: { // get_char has 3 particular return values: // a.) the next character represented as an integer // b.) undefined to signal that no data is currently available // c.) null to signal an EOF get_char: function(tty) { if (!tty.input.length) { var result = null; if (ENVIRONMENT_IS_NODE) { result = process['stdin']['read'](); if (!result) { if (process['stdin']['_readableState'] && process['stdin']['_readableState']['ended']) { return null; // EOF } return undefined; // no data available } } else if (typeof window != 'undefined' && typeof window.prompt == 'function') { // Browser. result = window.prompt('Input: '); // returns null on cancel if (result !== null) { result += '\n'; } } else if (typeof readline == 'function') { // Command line. result = readline(); if (result !== null) { result += '\n'; } } if (!result) { return null; } tty.input = intArrayFromString(result, true); } return tty.input.shift(); }, put_char: function(tty, val) { if (val === null || val === {{{ charCode('\n') }}}) { Module['print'](tty.output.join('')); tty.output = []; } else { tty.output.push(TTY.utf8.processCChar(val)); } } }, default_tty1_ops: { put_char: function(tty, val) { if (val === null || val === {{{ charCode('\n') }}}) { Module['printErr'](tty.output.join('')); tty.output = []; } else { tty.output.push(TTY.utf8.processCChar(val)); } } } } });