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.
Posted on 2003-01-31 03:21:02 by 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;


Posted on 2003-02-01 01:33:39 by rhyde