diff --git a/assets/disk0/home/hdk/compile.js b/assets/disk0/home/hdk/compile.js index aaf4b4f..0095df1 100644 --- a/assets/disk0/home/hdk/compile.js +++ b/assets/disk0/home/hdk/compile.js @@ -1,6 +1,6 @@ if (exec_args[1] === undefined) { println("Usage: compile -le/-lo myfile.js") - println(" The compiled and linked file will be myfile.out") + println(" The compiled and linked file will be myfile.exc") return 1 } @@ -14,7 +14,7 @@ if (exec_args[2]) { _G.shell.execute(`rm ${tempFilename}.gz`) _G.shell.execute(`link -${exec_args[1][2]} ${tempFilename}.bin`) - _G.shell.execute(`mv ${tempFilename}.out ${filenameWithoutExt}.out`) + _G.shell.execute(`mv ${tempFilename}.exc ${filenameWithoutExt}.exc`) _G.shell.execute(`rm ${tempFilename}.bin`) } // with no linking diff --git a/assets/disk0/home/hdk/decompile.js b/assets/disk0/home/hdk/decompile.js index 0d9f177..7a5fca3 100644 --- a/assets/disk0/home/hdk/decompile.js +++ b/assets/disk0/home/hdk/decompile.js @@ -1,6 +1,6 @@ if (exec_args[1] === undefined) { - println("Usage: decompile myfile.bin") - println("The compiled file will be myfile.bin.js") + println("Usage: decompile myfile.exc") + println("The compiled file will be myfile.exc.js") return 1 } _G.shell.execute(`enc ${exec_args[1]} ${exec_args[1]}.gz`) diff --git a/assets/disk0/home/hdk/enc.js b/assets/disk0/home/hdk/enc.js index c280374..ac0cd28 100644 --- a/assets/disk0/home/hdk/enc.js +++ b/assets/disk0/home/hdk/enc.js @@ -1,3 +1,5 @@ +// a simple, symmetric obfuscator with infinite-length key + function seq(s) { let out = "" let cnt = 0 diff --git a/assets/disk0/home/hdk/link.js b/assets/disk0/home/hdk/link.js index 2c84291..22b4b5d 100644 --- a/assets/disk0/home/hdk/link.js +++ b/assets/disk0/home/hdk/link.js @@ -11,7 +11,6 @@ let infile = files.open(infilePath) if (!infile.exists) throw Error("No such file: " + infilePath) -let outfile = files.open(infilePath.substringBeforeLast(".") + ".out") let outMode = exec_args[1].toLowerCase() let type = { @@ -21,6 +20,13 @@ let type = { "-c": "\x04" } +let ext = { + "-r": ".exc", // executable + "-e": ".exc", // executable + "-o": ".lib", // library + "-c": ".cob" // core object +} + function toI32(num) { const buffer = new ArrayBuffer(4) const view = new DataView(buffer) @@ -40,6 +46,7 @@ let addr = 0 if (exec_args[3] !== undefined && exec_args[3].toLowerCase() == "-a" && exec_args[4] !== undefined) addr = parseInt(exec_args[4], 16) +let outfile = files.open(infilePath.substringBeforeLast(".") + ext[exec_args[3].toLowerCase()]) outfile.sappend("\x20\xC0\xCC\x0A") outfile.sappend(type[outMode] || "\x00") outfile.bappend(toI24(addr)) diff --git a/assets/disk0/home/hdk/load.js b/assets/disk0/home/hdk/load.js index 31f6870..a950684 100644 --- a/assets/disk0/home/hdk/load.js +++ b/assets/disk0/home/hdk/load.js @@ -1,5 +1,5 @@ if (exec_args[1] === undefined) { - println("Usage: load myfile.out") + println("Usage: load myfile.exc") println(" This will load the binary image onto the Core Memory") return 1 } diff --git a/assets/disk0/tvdos/include/getopt.mjs b/assets/disk0/tvdos/include/getopt.mjs new file mode 100644 index 0000000..15525ba --- /dev/null +++ b/assets/disk0/tvdos/include/getopt.mjs @@ -0,0 +1,305 @@ +/* + * getopt.js: node.js implementation of POSIX getopt() (and then some) + * + * Copyright 2011 David Pacheco. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +var ASSERT = require('assert').ok; + +function goError(msg) +{ + return (new Error('getopt: ' + msg)); +} + +/* + * The BasicParser is our primary interface to the outside world. The + * documentation for this object and its public methods is contained in + * the included README.md. + */ +function goBasicParser(optstring, argv, optind) +{ + var ii; + + ASSERT(optstring || optstring === '', 'optstring is required'); + ASSERT(optstring.constructor === String, 'optstring must be a string'); + ASSERT(argv, 'argv is required'); + ASSERT(argv.constructor === Array, 'argv must be an array'); + + this.gop_argv = new Array(argv.length); + this.gop_options = {}; + this.gop_aliases = {}; + this.gop_optind = optind !== undefined ? optind : 2; + this.gop_subind = 0; + + for (ii = 0; ii < argv.length; ii++) { + ASSERT(argv[ii].constructor === String, + 'argv must be string array'); + this.gop_argv[ii] = argv[ii]; + } + + this.parseOptstr(optstring); +} + +exports.BasicParser = goBasicParser; + +/* + * Parse the option string and update the following fields: + * + * gop_silent Whether to log errors to stderr. Silent mode is + * indicated by a leading ':' in the option string. + * + * gop_options Maps valid single-letter-options to booleans indicating + * whether each option is required. + * + * gop_aliases Maps valid long options to the corresponding + * single-letter short option. + */ +goBasicParser.prototype.parseOptstr = function (optstr) +{ + var chr, cp, alias, arg, ii; + + ii = 0; + if (optstr.length > 0 && optstr[0] == ':') { + this.gop_silent = true; + ii++; + } else { + this.gop_silent = false; + } + + while (ii < optstr.length) { + chr = optstr[ii]; + arg = false; + + if (!/^[\w\d\u1000-\u1100]$/.test(chr)) + throw (goError('invalid optstring: only alphanumeric ' + + 'characters and unicode characters between ' + + '\\u1000-\\u1100 may be used as options: ' + chr)); + + if (ii + 1 < optstr.length && optstr[ii + 1] == ':') { + arg = true; + ii++; + } + + this.gop_options[chr] = arg; + + while (ii + 1 < optstr.length && optstr[ii + 1] == '(') { + ii++; + cp = optstr.indexOf(')', ii + 1); + if (cp == -1) + throw (goError('invalid optstring: missing ' + + '")" to match "(" at char ' + ii)); + + alias = optstr.substring(ii + 1, cp); + this.gop_aliases[alias] = chr; + ii = cp; + } + + ii++; + } +}; + +goBasicParser.prototype.optind = function () +{ + return (this.gop_optind); +}; + +/* + * For documentation on what getopt() does, see README.md. The following + * implementation invariants are maintained by getopt() and its helper methods: + * + * this.gop_optind Refers to the element of gop_argv that contains + * the next argument to be processed. This may + * exceed gop_argv, in which case the end of input + * has been reached. + * + * this.gop_subind Refers to the character inside + * this.gop_options[this.gop_optind] which begins + * the next option to be processed. This may never + * exceed the length of gop_argv[gop_optind], so + * when incrementing this value we must always + * check if we should instead increment optind and + * reset subind to 0. + * + * That is, when any of these functions is entered, the above indices' values + * are as described above. getopt() itself and getoptArgument() may both be + * called at the end of the input, so they check whether optind exceeds + * argv.length. getoptShort() and getoptLong() are called only when the indices + * already point to a valid short or long option, respectively. + * + * getopt() processes the next option as follows: + * + * o If gop_optind > gop_argv.length, then we already parsed all arguments. + * + * o If gop_subind == 0, then we're looking at the start of an argument: + * + * o Check for special cases like '-', '--', and non-option arguments. + * If present, update the indices and return the appropriate value. + * + * o Check for a long-form option (beginning with '--'). If present, + * delegate to getoptLong() and return the result. + * + * o Otherwise, advance subind past the argument's leading '-' and + * continue as though gop_subind != 0 (since that's now the case). + * + * o Delegate to getoptShort() and return the result. + */ +goBasicParser.prototype.getopt = function () +{ + if (this.gop_optind >= this.gop_argv.length) + /* end of input */ + return (undefined); + + var arg = this.gop_argv[this.gop_optind]; + + if (this.gop_subind === 0) { + if (arg == '-' || arg === '' || arg[0] != '-') + return (undefined); + + if (arg == '--') { + this.gop_optind++; + this.gop_subind = 0; + return (undefined); + } + + if (arg[1] == '-') + return (this.getoptLong()); + + this.gop_subind++; + ASSERT(this.gop_subind < arg.length); + } + + return (this.getoptShort()); +}; + +/* + * Implements getopt() for the case where optind/subind point to a short option. + */ +goBasicParser.prototype.getoptShort = function () +{ + var arg, chr; + + ASSERT(this.gop_optind < this.gop_argv.length); + arg = this.gop_argv[this.gop_optind]; + ASSERT(this.gop_subind < arg.length); + chr = arg[this.gop_subind]; + + if (++this.gop_subind >= arg.length) { + this.gop_optind++; + this.gop_subind = 0; + } + + if (!(chr in this.gop_options)) + return (this.errInvalidOption(chr)); + + if (!this.gop_options[chr]) + return ({ option: chr }); + + return (this.getoptArgument(chr)); +}; + +/* + * Implements getopt() for the case where optind/subind point to a long option. + */ +goBasicParser.prototype.getoptLong = function () +{ + var arg, alias, chr, eq; + + ASSERT(this.gop_subind === 0); + ASSERT(this.gop_optind < this.gop_argv.length); + arg = this.gop_argv[this.gop_optind]; + ASSERT(arg.length > 2 && arg[0] == '-' && arg[1] == '-'); + + eq = arg.indexOf('='); + alias = arg.substring(2, eq == -1 ? arg.length : eq); + if (!(alias in this.gop_aliases)) + return (this.errInvalidOption(alias)); + + chr = this.gop_aliases[alias]; + ASSERT(chr in this.gop_options); + + if (!this.gop_options[chr]) { + if (eq != -1) + return (this.errExtraArg(alias)); + + this.gop_optind++; /* eat this argument */ + return ({ option: chr }); + } + + /* + * Advance optind/subind for the argument value and retrieve it. + */ + if (eq == -1) + this.gop_optind++; + else + this.gop_subind = eq + 1; + + return (this.getoptArgument(chr)); +}; + +/* + * For the given option letter 'chr' that takes an argument, assumes that + * optind/subind point to the argument (or denote the end of input) and return + * the appropriate getopt() return value for this option and argument (or return + * the appropriate error). + */ +goBasicParser.prototype.getoptArgument = function (chr) +{ + var arg; + + if (this.gop_optind >= this.gop_argv.length) + return (this.errMissingArg(chr)); + + arg = this.gop_argv[this.gop_optind].substring(this.gop_subind); + this.gop_optind++; + this.gop_subind = 0; + return ({ option: chr, optarg: arg }); +}; + +goBasicParser.prototype.errMissingArg = function (chr) +{ + if (this.gop_silent) + return ({ option: ':', optopt: chr }); + + process.stderr.write('option requires an argument -- ' + chr + '\n'); + return ({ option: '?', optopt: chr, error: true }); +}; + +goBasicParser.prototype.errInvalidOption = function (chr) +{ + if (!this.gop_silent) + process.stderr.write('illegal option -- ' + chr + '\n'); + + return ({ option: '?', optopt: chr, error: true }); +}; + +/* + * This error is not specified by POSIX, but neither is the notion of specifying + * long option arguments using "=" in the same argv-argument, but it's common + * practice and pretty convenient. + */ +goBasicParser.prototype.errExtraArg = function (chr) +{ + if (!this.gop_silent) + process.stderr.write('option expects no argument -- ' + + chr + '\n'); + + return ({ option: '?', optopt: chr, error: true }); +}; diff --git a/tsvm_core/src/net/torvald/tsvm/JS_INIT.js b/tsvm_core/src/net/torvald/tsvm/JS_INIT.js index 0e68682..b9e7178 100644 --- a/tsvm_core/src/net/torvald/tsvm/JS_INIT.js +++ b/tsvm_core/src/net/torvald/tsvm/JS_INIT.js @@ -375,6 +375,9 @@ Array.prototype.shuffle = function() { return this; } +Array.prototype.shuffled = function() { + return this.slice(0).shuffle() +} Array.prototype.sum = function(selector) { return this.reduce((acc,val) => acc + ((selector === undefined) ? val : selector(val)), 0) }