Cleaned up the integer base conversion code, and expanded the PDP-10 register dump

This commit is contained in:
Jeff Parsons 2017-02-27 19:18:19 -08:00 committed by Jeff Parsons
commit c4f7262e71
11 changed files with 3457 additions and 3466 deletions

View file

@ -143,6 +143,48 @@ class Str {
return value;
}
/**
* toBase(n, radix, cch, sPrefix)
*
* Displays the given number as an unsigned integer using the specified radix and number of digits.
*
* @param {number|null|undefined} n
* @param {number} radix (ie, the base)
* @param {number} cch (the desired number of digits)
* @param {string} [sPrefix] (default is none)
* @return {string}
*/
static toBase(n, radix, cch, sPrefix = "")
{
/*
* An initial "falsey" check for null takes care of both null and undefined;
* we can't rely entirely on isNaN(), because isNaN(null) returns false, oddly enough.
*
* Alternatively, we could mask and shift n regardless of whether it's null/undefined/NaN,
* since JavaScript coerces such operands to zero, but I think there's "value" in seeing those
* values displayed differently.
*/
var s = "";
if (n == null || isNaN(n)) {
while (cch-- > 0) s = '?' + s;
} else {
/*
* Callers that produced an input by dividing by a power of two rather than shifting (in order
* to access more than 32 bits) may produce a fractional result, which ordinarily we would simply
* ignore, but if the integer portion is zero and the sign is negative, we should probably treat
* this value as a sign-extension.
*/
if (n < 0 && n > -1) n = -1;
while (cch-- > 0) {
var d = n % radix;
d += (d >= 0 && d <= 9? 0x30 : 0x41 - 10);
s = String.fromCharCode(d) + s;
n = Math.trunc(n / radix);
}
}
return sPrefix + s;
}
/**
* toBin(n, cch, grouping)
*
@ -208,106 +250,54 @@ class Str {
/**
* toOct(n, cch, fPrefix)
*
* Converts an integer to octal, with the specified number of digits (default of 6; max of 11)
* Converts an integer to octal, with the specified number of digits (default of 6; max of 12)
*
* You might be tempted to use the built-in n.toString(8) instead, but it doesn't zero-pad and it
* doesn't properly convert negative values. Moreover, if n is undefined, n.toString() will throw
* an exception, whereas this function will return '?' characters.
*
* @param {number|null|undefined} n (interpreted as a 32-bit value)
* @param {number|null|undefined} n (supports integers up to 36 bits now)
* @param {number} [cch] is the desired number of octal digits (0 or undefined for default of either 6 or 11)
* @param {boolean} [fPrefix]
* @return {string} the octal representation of n
*/
static toOct(n, cch, fPrefix)
{
var s = "";
if (cch) {
if (cch > 11) cch = 11;
if (cch > 12) cch = 12;
} else {
cch = (n & ~0xffffff)? 11 : ((n & ~0xffff)? 8 : 6);
}
/*
* An initial "falsey" check for null takes care of both null and undefined;
* we can't rely entirely on isNaN(), because isNaN(null) returns false, oddly enough.
*
* Alternatively, we could mask and shift n regardless of whether it's null/undefined/NaN,
* since JavaScript coerces such operands to zero, but I think there's "value" in seeing those
* values displayed differently.
*/
if (n == null || isNaN(n)) {
while (cch-- > 0) s = '?' + s;
} else {
/*
* Callers that produced an input by dividing by a power of two rather than shifting (in order
* to access more than 32 bits) may produce a fractional result, which ordinarily we would simply
* ignore, but if the integer portion is zero and the sign is negative, we should probably treat
* this value as a sign-extension.
*/
if (n < 0 && n > -1) n = -1;
while (cch-- > 0) {
var d = (n & 7) + 0x30;
s = String.fromCharCode(d) + s;
n >>= 3;
}
}
return (fPrefix? "0o" : "") + s;
return Str.toBase(n, 8, cch, fPrefix? "0o" : "");
}
/**
* toDec(n, cch)
*
* Converts an integer to decimal, with the specified number of digits (default of 5; max of 10)
* Converts an integer to decimal, with the specified number of digits (default of 5; max of 11)
*
* You might be tempted to use the built-in n.toString(10) instead, but it doesn't zero-pad and it
* doesn't properly convert negative values. Moreover, if n is undefined, n.toString() will throw
* an exception, whereas this function will return '?' characters.
*
* @param {number|null|undefined} n (interpreted as a 32-bit value)
* @param {number|null|undefined} n (supports integers up to 36 bits now)
* @param {number} [cch] is the desired number of decimal digits (0 or undefined for default of either 5 or 10)
* @return {string} the decimal representation of n
*/
static toDec(n, cch)
{
var s = "";
if (cch) {
if (cch > 10) cch = 10;
if (cch > 11) cch = 11;
} else {
cch = (n & ~0xffff)? 10 : 5;
}
/*
* An initial "falsey" check for null takes care of both null and undefined;
* we can't rely entirely on isNaN(), because isNaN(null) returns false, oddly enough.
*
* Alternatively, we could mask and shift n regardless of whether it's null/undefined/NaN,
* since JavaScript coerces such operands to zero, but I think there's "value" in seeing those
* values displayed differently.
*/
if (n == null || isNaN(n)) {
while (cch-- > 0) s = '?' + s;
} else {
/*
* Callers that produced an input by dividing by a power of two rather than shifting (in order
* to access more than 32 bits) may produce a fractional result, which ordinarily we would simply
* ignore, but if the integer portion is zero and the sign is negative, we should probably treat
* this value as a sign-extension.
*/
if (n < 0 && n > -1) n = -1;
while (cch-- > 0) {
var d = (n % 10) + 0x30;
s = String.fromCharCode(d) + s;
n /= 10;
}
}
return s;
return Str.toBase(n, 10, cch);
}
/**
* toHex(n, cch, fPrefix)
*
* Converts an integer to hex, with the specified number of digits (default of 4 or 8, max of 8).
* Converts an integer to hex, with the specified number of digits (default of 4 or 8, max of 9).
*
* You might be tempted to use the built-in n.toString(16) instead, but it doesn't zero-pad and it
* doesn't properly convert negative values; for example, if n is -2147483647, then n.toString(16)
@ -321,46 +311,19 @@ class Str {
* s = "00000000".substr(0, 8 - s.length) + s;
* s = s.substr(0, cch).toUpperCase();
*
* @param {number|null|undefined} n (interpreted as a 32-bit value)
* @param {number|null|undefined} n (supports integers up to 36 bits now)
* @param {number} [cch] is the desired number of hex digits (0 or undefined for default of either 4 or 8)
* @param {boolean} [fPrefix]
* @return {string} the hex representation of n
*/
static toHex(n, cch, fPrefix)
{
var s = "";
if (cch) {
if (cch > 8) cch = 8;
if (cch > 9) cch = 9;
} else {
cch = (n & ~0xffff)? 8 : 4;
}
/*
* An initial "falsey" check for null takes care of both null and undefined;
* we can't rely entirely on isNaN(), because isNaN(null) returns false, oddly enough.
*
* Alternatively, we could mask and shift n regardless of whether it's null/undefined/NaN,
* since JavaScript coerces such operands to zero, but I think there's "value" in seeing those
* values displayed differently.
*/
if (n == null || isNaN(n)) {
while (cch-- > 0) s = '?' + s;
} else {
/*
* Callers that produced an input by dividing by a power of two rather than shifting (in order
* to access more than 32 bits) may produce a fractional result, which ordinarily we would simply
* ignore, but if the integer portion is zero and the sign is negative, we should probably treat
* this value as a sign-extension.
*/
if (n < 0 && n > -1) n = -1;
while (cch-- > 0) {
var d = n & 0xf;
d += (d >= 0 && d <= 9? 0x30 : 0x41 - 10);
s = String.fromCharCode(d) + s;
n >>= 4;
}
}
return (fPrefix? "0x" : "") + s;
return Str.toBase(n, 16, cch, fPrefix? "0x" : "");
}
/**