stdlib: fix memory leak on file errors

stdlib: throw runtime error when reading invalid real number

stdlib: bugfix val (real) for empty strings

tdrimg: add another demo image
This commit is contained in:
slederer 2025-08-22 02:20:21 +02:00
parent 0ea7dcef29
commit 95cc02ffcb
3 changed files with 40 additions and 11 deletions

View file

@ -1183,7 +1183,17 @@ ext:
code := 0;
end
else
code := i - 1;
begin
if i = 1 then (* empty string gives error position 1 *)
code := 1
else
code := i - 1;
end;
end;
procedure errorhalt(var fil:file);
begin
RuntimeError(ioerrordesc[fil.lastError]);
end;
procedure checkerror(var fil:file);
@ -1191,7 +1201,7 @@ begin
if fil.lastError <> 0 then
begin
if not fil.errorAck then
RuntimeError(ioerrordesc[fil.lastError])
errorhalt(fil)
else
begin
fil.lastError := 0;
@ -1334,12 +1344,16 @@ procedure freadreal(var v:real;var f:file);
var buf:string[40];
errpos:integer;
begin
errpos := -1;
fskipwhite(f);
fscanbuf(f,ScanReal, buf);
if f.lastError = 0 then
val(buf, v, errpos);
if errpos <> 0 then
begin
fileerror(f, IOInvalidFormat);
checkerror(f);
end;
end;
procedure freadstring(var s:string; var f:file);
@ -1665,12 +1679,21 @@ begin
{ writeln(' readbuf data: ', fil.buffer^[0][0]); }
end;
procedure close(var aFile:file); forward;
(* Set error state on file and close it.
Buffer will not be flushed as that might
have caused the error.
*)
procedure fileerror(var fil:file; error:integer);
begin
(* should check if there was an error already
and throw a runtime error in that case *)
fil.lastError := error;
fil.errorAck := false;
if fil.buffer <> nil then
begin
fil.needsflush := false;
close(fil);
end;
end;
function IOResult(var fil:file):integer;
@ -2052,19 +2075,22 @@ procedure close(var aFile:file);
begin
if aFile.typ = IODiskFile then
begin
if aFile.lastError = IOFileClosed then
errorhalt(aFile);
{ writeln('close needsflush:', aFile.needsflush, ' changed:', aFile.changed, ' error:', aFile.lastError); }
if aFile.needsflush then
flushfile(aFile);
{ writeln('close f.buffer:', aFile.buffer); }
dispose(aFile.buffer);
aFile.buffer := nil;
if aFile.lastError = 0 then
begin
fileerror(aFile, IOFileClosed);
{ writeln('close f.buffer:', aFile.buffer); }
dispose(aFile.buffer);
aFile.buffer := nil;
if aFile.changed then
updatedirslot(aFile);
if aFile.lastError = 0 then
fileerror(aFile, IOFileClosed);
end;
closevolumeid(aFile.volumeid);