Reputation: 9238
I'm working on some legacy software written in Delphi 7 which runs on Windows. I've minified the problem to the following program:
var f: text;
begin
assign(f, 'a.txt');
rewrite(f);
writeln(f, 'before' + chr(14) + 'after');
close(f);
assign(f, 'a.txt');
append(f);
close(f);
end.
I expect it to create a.txt
file containing "before#14after#13#10"
and then append nothing to it. However, after I run this program on Windows, I see before
in a.txt
instead, like if Delphi's append
truncates the file. If I do not re-open the file, it shows before#14after#13#10
as expected.
If I write something (FooBar
) in the re-opened file, it's appended, but as if the file was already truncated: beforeFooBar
.
This effect does not occur with any other character between 0 and 32, even with 26 (which stands for EOF).
Is this a bug in Delphi or a well-defined behavior? What is so special about chr(14)
?
Upvotes: 6
Views: 241
Reputation: 9238
Thanks to some friends from a chat and Sertac Akyuz from comments: it looks like a bug in Delphi 7.
It's supposed to have special handling of the EOF symbol (ASCII 26), quoting from here:
Note: If a Ctrl+Z (ASCII 26) is present in the last 128-byte block of the file, the current file position is set so that the next character added to the file overwrites the first Ctrl+Z in the block. In this way, text can be appended to a file that terminates with a Ctrl+Z.
Kind of CP/M backward compatibility, I guess.
However, there is a bug in the implementation of TextOpen
for Windows (see Source/Rtl/Sys/System.pas
from your Delphi 7 installation around line 4282):
@@loop:
CMP EAX,EDX
JAE @@success
// if (f.Buffer[i] == eof)
CMP byte ptr [ESI].TTextRec.Buffer[EAX],eof
JE @@truncate
INC EAX
JMP @@loop
Here it says eof
instead of cEof
. Unfortunatley, that compiles for some reason and it even appeared on StackOverflow already. There is a label called @@eof
and that's pretty much it.
Consequence: instead of having special case for 26, we have special case for 14. The exact reason is yet to be found.
Upvotes: 5