I have a file, which ends with 3 (exactly) hexadecimal digits.
The following code:
The manual says "...a string of one or more hexadecimal digits....must end with a valid delimiter character or the end of the file."
clone-d.
The following code:
mov( file_size, eax );
sub( 3, eax );
fileio.seek( my_file, eax );
fileio.getw( my_file );
raises an exception (12) "End of file error".
The manual says "...a string of one or more hexadecimal digits....must end with a valid delimiter character or the end of the file."
clone-d.
I have a file, which ends with 3 (exactly) hexadecimal digits.
The following code:
mov( file_size, eax );
sub( 3, eax );
fileio.seek( my_file, eax );
fileio.getw( my_file );
raises an exception (12) "End of file error".
The manual says "...a string of one or more hexadecimal digits....must end with a valid delimiter character or the end of the file."
clone-d.
Yes, that appears to be the case.
Looking at the getq source code (getw calls getd, which calls getq, which does the actual I/O and conversion) there is absolutely no check for EOF at all. To correct this problem,
inset the lines I've marked with "//***" into the fgetq.hla source file, do a clean on the HLA Standard Library, and rebuild it (if you don't have MASM, LINK, and LIB, just recompile the fgetq file and link it with your code).
Note: I'd expect this same problem to exist elsewhere in the standard library.
The solution will generally be the same.
I'll try to get all this fixed up by the v1.43 release.
Randy Hyde
unit FileIOUnit;
#include( "fileiounit.hhf" )
/*********************************************/
/* */
/* fgetq- */
/* */
/* Reads a 64-bit hexadecimal value from the */
/* specified file. Returns the value in */
/* EDX:EAX. */
/* */
/*********************************************/
procedure fgetq( Handle:dword ); @nodisplay; @noalignstack;
var
Delimiters: cset;
begin fgetq;
push( ecx );
conv.getDelimiters( Delimiters );
xor( eax, eax );
xor( edx, edx );
xor( ecx, ecx );
begin EncounteredEOF; //****
// Skip over any leading delimiters:
repeat
exitif( feof( Handle )) EncounteredEOF; //****
fgetc( Handle );
until(#{ bt( eax, (type dword Delimiters )); jc false; }#);
// Okay, input the digits and convert to a number:
repeat
// The character must be a numeric digit.
// The following code converts the character in
// al to the range $FA..$FF, $00..$09 if it is
// a hexadecimal character.
sub( '0', al );
if( al >= 10 ) then
sub( $17, al );
if( al < $FA ) then
raise( ex.ConversionError );
endif;
endif;
shl( 1, ecx ); // Multiply edx:ecx by 16.
rcl( 1, edx );
jc Overflow;
shl( 1, ecx ); // This is *4.
rcl( 1, edx );
jc Overflow;
shl( 1, ecx ); // This is *8.
rcl( 1, edx );
jc Overflow;
shl( 1, ecx ); // This is *16.
rcl( 1, edx );
jc Overflow;
// Add in the current character:
add( eax, ecx );
adc( 0, edx );
jnc NoOverflow;
Overflow:
raise( ex.ValueOutOfRange );
NoOverflow:
// Skip any underscores in the middle of the number.
repeat
exitif( feof( Handle )) EncounteredEOF; //****
fgetc( Handle );
until( al <> '_' );
movzx( al, eax );
until(#{ bt( eax, (type dword Delimiters )); jnc false; }#);
end EncounteredEOF; //****
mov( ecx, eax );
pop( ecx );
end fgetq;
end FileIOUnit;