@@ -430,12 +430,36 @@ class StdIO extends NumIO {
430430
431431case 'd' :
432432/*
433- * We could use "arg |= 0", but there may be some value to supporting integers > 32 bits.
433+ * I could use "arg |= 0", but there may be some value to supporting integers > 32 bits,
434+ * so I use Math.trunc() instead. Bit-wise operators also mask a lot of evils, by converting
435+ * complete nonsense into zero, so while I'm ordinarily a fan, that's not desirable here.
434436 *
435- * Also, unlike the 'X' and 'x' hexadecimal cases, there's no need to explicitly check for string
436- * arguments, because Math.trunc() automatically coerces any string value to a (decimal) number.
437+ * Other (hidden) advantages of Math.trunc(): it automatically converts strings, it honors
438+ * numeric prefixes (the traditional "0x" for hex and the newer "0o" for octal), and it returns
439+ * NaN if the ENTIRE string cannot be converted.
440+ *
441+ * parseInt(), which would seem to be the more logical choice here, doesn't understand "0o",
442+ * doesn't return NaN if non-digits are embedded in the string, and doesn't behave consistently
443+ * across all browsers when parsing older octal values with a leading "0"; Math.trunc() doesn't
444+ * recognize those octal values either, but I'm OK with that, as long as it CONSISTENTLY doesn't
445+ * recognize them.
446+ *
447+ * That last problem is why some recommend that you ALWAYS pass a radix to parseInt(), but that
448+ * forces you to parse the string first and determine the proper radix; otherwise, you end up
449+ * with NEW inconsistencies. For example, if radix is 10 and the string is "0x10", the result
450+ * is zero, since parseInt() happily stops parsing when it reaches the first non-radix 10 digit.
437451 */
438452arg = Math . trunc ( arg ) ;
453+ /*
454+ * Before falling into the decimal floating-point code, we take this opportunity to convert
455+ * the precision value, if any, to the minimum number of digits to print. Which basically means
456+ * setting zeroPad to true, width to precision, and then unsetting precision.
457+ */
458+ if ( precision >= 0 ) {
459+ zeroPad = true ;
460+ if ( width < precision ) width = precision ;
461+ precision = - 1 ;
462+ }
439463/* falls through */
440464
441465case 'f' :
@@ -474,9 +498,11 @@ class StdIO extends NumIO {
474498
475499case 's' :
476500/*
477- * 's' includes some non-standard behavior, such as coercing non-strings to strings first.
501+ * 's' includes some non-standard benefits, such as coercing non-strings to strings first;
502+ * we know undefined and null values don't have a toString() method, but hopefully everything
503+ * else does.
478504 */
479- if ( arg !== undefined ) {
505+ if ( arg != undefined ) {
480506if ( typeof arg != "string" ) {
481507arg = arg . toString ( ) ;
482508}
@@ -501,25 +527,23 @@ class StdIO extends NumIO {
501527
502528case 'X' :
503529ach = StdIO . HexUpperCase ;
504- // if (hash) prefix = "0X"; // I don't like that %#X uppercasesboth the prefix and the value
530+ // if (hash) prefix = "0X"; // I don't like that %#X uppercasesBOTH the prefix and the value
505531/* falls through */
506532
507533case 'x' :
508534s = "" ;
509535if ( ! radix ) radix = 16 ;
510536if ( ! prefix && hash ) prefix = "0x" ;
511537if ( ! ach ) ach = StdIO . HexLowerCase ;
512- if ( typeof arg == "string" ) {
513- /*
514- * Since we're advised to ALWAYS pass a radix to parseInt(), we must detect explicitly
515- * hex values ourselves, because using a radix of 10 with any "0x..." value always returns 0.
516- *
517- * And if the value CAN be interpreted as decimal, then we MUST interpret it as decimal, because
518- * we have sprintf() calls in /modules/pcx86/lib/testmon.js that depend on this code to perform
519- * decimal to hex conversion. We're going to make our own rules here, since passing numbers in
520- * string form isn't part of the sprintf "spec".
521- */
522- arg = Number . parseInt ( arg , arg . match ( / ( ^ 0 x | [ a - f ] ) / i) ?16 :10 ) ;
538+ /*
539+ * For all the same reasons articulated above (for type 'd'), we pass the arg through Math.trunc(),
540+ * and we honor precision, if any, as the minimum number of digits to print.
541+ */
542+ arg = Math . trunc ( arg ) ;
543+ if ( precision >= 0 ) {
544+ zeroPad = true ;
545+ if ( width < precision ) width = precision ;
546+ precision = - 1 ;
523547}
524548if ( zeroPad && ! width ) {
525549/*