$include (..\lib\compStch.ext) /* *============================================================================ * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE * * Permission to use for any purpose, modify, copy, and make enhancements * and derivative works of the software is granted if attribution is given to * R.M. Gillmore, dba the ACME Software Deli, as the author * * While the ACME Software Deli does not work for money, there is nonetheless * a significant amount of work involved. The ACME Software Deli maintains the * rights to all code written, though it may be used and distributed as long as * the following conditions are maintained. * * 1. The copyright statement at the top of each code block is maintained in * your distribution. * 2. You do not identify yourself as the ACME Software Deli * 3. Any changes made to the software are sent to the ACME Software Deli *============================================================================ */ /* * Common numeric to ASCII conversions */ numStrsModule: do; $if not noID declare IDString (*) byte data ( '@(#)numStrs.p86 $Author: rmgillmore $ $Date:: 2025-05-04 19:35:39#$:', 0 ); $endif $set (numStrs_Implementation) $include (..\lib\comnDefs.ext) $include (..\lib\sysCalls.ext) $include (..\lib\string.ext) $include (..\lib\fileIO.ext) $include (..\lib\numStrs.ext) declare xlatChar (*) byte data ( '0123456789abcdef' ); byteToHexString: procedure ( byteIn, stringPtr ) reentrant public; declare byteIn byte, stringPtr pointer, string based stringPtr (*) byte; string( 0 ) = xlatChar( shr( byteIn, 4 ) and 0fh ); string( 1 ) = xlatChar( byteIn and 0fh ); string( 2 ) = 'h'; string( 3 ) = NUL; end byteToHexString; /* ******************************* */ byteToDecimalString: procedure ( byteIn, stringPtr ) reentrant public; declare byteIn byte, stringPtr pointer, localDword dword; localDword = double( double( byteIn ) ); call dwordToDecimalString( localDword, stringPtr ); end byteToDecimalString; /* ******************************* */ booleanToString: procedure ( booleanIn, stringPtr ) reentrant public; declare booleanIn boolean, stringPtr pointer, string based stringPtr (*) byte; string( 0 ) = NUL; if ( booleanIn ) then call strncat( @string, @( 'TRUE', 0 ), 10 ); else call strncat( @string, @( 'FALSE', 0 ), 10 ); end booleanToString; /* ******************************* */ wordToHexString: procedure ( wordIn, stringPtr ) reentrant public; declare wordIn word, stringPtr pointer; declare string based stringPtr (*) byte; call byteToHexString( high( wordIn ), @string( 0 ) ); call byteToHexString( low( wordIn ), @string( 2 ) ); end wordToHexString; /* ******************************* */ wordToDecimalString: procedure ( wordIn, stringPtr ) reentrant public; declare wordIn word, stringPtr pointer, localDword dword; localDword = double( wordIn ); call dwordToDecimalString( localDword, stringPtr ); end wordToDecimalString; /* ******************************* */ dwordToHexString: procedure ( dwordIn, stringPtr ) reentrant public; declare dwordIn dword, stringPtr pointer; declare string based stringPtr (*) byte; call wordToHexString( high( dwordIn ), @string( 0 ) ); call wordToHexString( low( dwordIn ), @string( 4 ) ); end dwordToHexString; /* ******************************* */ dwordToDecimalString: procedure ( dwordIn, stringPtr ) reentrant public; declare dwordIn dword, stringPtr pointer, returnString based stringPtr (*) byte; /* * unlike the Hex counterpart, the divisions are not on byte or word boundaries, * so we must repeat the same as with the integer (which is also reported in * decimal format). DWord values are always unsigned */ /* * 4294967295 is 2^32 - 1, the largest decimal value that will fit, plus one * for the NUL character */ declare NUMBER_DIGITS literally '12'; declare reverseResults ( NUMBER_DIGITS ) byte, localValue dword, previousValue dword, remainder dword, stringIndex integer, outIndex integer; previousValue, localValue = dwordIn; stringIndex = 0; if ( localValue = 0 ) then do; returnString( 0 ) = '0'; outIndex = 1; end; else do; do while ( localValue <> 0 ); remainder = localValue mod 10; localValue = localValue / 10; reverseResults( stringIndex ) = xlatChar( low( remainder ) ); previousValue = localValue; stringIndex = stringIndex + 1; end; /* while value > 0 */ reverseResults( stringIndex ) = NUL; stringIndex = stringIndex - 1; outIndex = 0; do while ( 0 <= stringIndex ); returnString( outIndex ) = reverseResults( stringIndex ); outIndex = outIndex + 1; stringIndex = stringIndex - 1; end; end; returnString( outIndex ) = NUL; end dwordToDecimalString; /* ******************************* */ pointerToHexString: procedure ( pointerIn, stringPtr ) reentrant public; declare pointerIn pointer, stringPtr pointer; declare string based stringPtr (*) byte, wordValue word, segment selector at ( @wordValue ), tempString (16) byte; segment = selector$of( pointerIn ); call wordToHexString( wordValue, @string( 0 ) ); string( 4 ) = ':'; call wordToHexString( offset$of( pointerIn ), @string( 5 ) ); end pointerToHexString; /* ******************************* */ integerToString: procedure ( integerIn, stringPtr ) reentrant public; declare integerIn integer, stringPtr pointer, returnString based stringPtr (*) byte; /* * Where did the 7 come from? Well, since integers on the 8086 are * 16 bits, that means the range of values are -32768 to 32767. That * means that there are 5 digits plus the sign maximum. The last byte * will be the nul terminating character. */ declare localString ( 7 ) byte, digitIndex integer, localInteger integer, valueNegative boolean; if ( integerIn = 0 ) then do; returnString( 0 ) = xlatChar( 0 ); returnString( 1 ) = NUL; end; else do; /* * Now comes the fun part. What we need to do is to translate from the * binary integer to ASCII. It's not as easy as masking off a specific * number of bits. We must account for the sign, then isolate the least * significant digit, translate the value to ASCII, and adjust the local * value until we are at zero */ localInteger = integerIn; if ( integerIn < 0 ) then do; localInteger = -localInteger; valueNegative = TRUE; end; else do; valueNegative = FALSE; end; /* * repeat the division until we are done */ do; declare results structure ( quotient integer, remainder integer ), outIndex integer; digitIndex = 0; do while ( 0 < localInteger ); call moddiv( localInteger, 10, @results ); localInteger = results.quotient; localString( digitIndex ) = xlatChar( results.remainder ); digitIndex = digitIndex + 1; end; digitIndex = digitIndex - 1; /* * starting at the end of the local string, transfer the bytes to the * string passed in, and we are done */ if ( valueNegative ) then do; returnString( 0 ) = '-'; outIndex = 1; end; else do; outIndex = 0; end; do while ( 0 <= digitIndex ); returnString( outIndex ) = localString( digitIndex ); outIndex = outIndex + 1; digitIndex = digitIndex - 1; end; returnString( outIndex ) = NUL; end; end; end integerToString; /* ******************************* */ varToString: procedure ( valuePtr, valueType, valueLabelString, userStringPtr ) reentrant public; declare valuePtr pointer, valueType integer, valueLabelString pointer, userStringPtr pointer; declare byteValue based valuePtr byte, wordValue based valuePtr word, dwordValue based valuePtr dword, pointerValue based valuePtr pointer, stringValue based valuePtr (*) byte, booleanValue based valuePtr boolean, integerValue based valuePtr integer; declare reportString ( 128 ) byte, numValueString ( 128 ) byte; numValueString( 0 ) = NUL; call strcpy( @reportString, valueLabelString ); call strcat( @reportString, @( ': ', 0 ) ); valueTypeCase: do case ( valueType ); do; /* byteType */ call byteToHexString( byteValue, @numValueString ); end; do; /* byteDecimalType */ call byteToDecimalString( byteValue, @numValueString ); end; do; /* wordType */ call wordToHexString( wordValue, @numValueString ); end; do; /* wordDecimalType */ call wordToDecimalString( wordValue, @numValueString ); end; do; /* dwordType */ call dwordToHexString( dwordValue, @numValueString ); end; do; /* dwordDecimalType */ call dwordToDecimalString( dwordValue, @numValueString ); end; do; /* pointerType */ call pointerToHexString( pointerValue, @numValueString ); end; do; /* stringType */ call strcpy( @numValueString, @stringValue ); end; do; /* booleanType */ call booleanToString( booleanValue, @numValueString ); end; do; /* integerType */ call integerToString( integerValue, @numValueString ); end; end valueTypeCase; call strcat( @reportString, @numValueString ); call strcpy( userStringPtr, @reportString ); end varToString; end numStrsModule;