[fpc-pascal] possible bug in blockwrite
Travis Siegel
tsiegel at softcon.com
Sun Mar 5 18:54:24 CET 2023
I'm using FPC 3.2.0, though I doubt anything changed in the most recent
releases, though I'll try those if folks think it's worth doing so.
What I ran across yesterday while doing a search for other things was
some posts about updating a single line in a file using free pascal.
The solutions mostly centered around using stream objects or the inifile
objects in lazarus.
This reminded me that I used to do this exact thing under turbo pascal
by using blockread/writes, and treating the text file as a binary one.
This allowed me to make changes without having to rewrite the whole
file, something even inifile still does.
To make a long story short, I tried that technique in FPC, and was a bit
surprised by the results.
What happens is this:
On tp, I could open a file with a blocksize of 1,
reset(file1,1);
which would allow me to move through the file, and blockread/blockwrite
whe ever I so chose to do so.
The problem with FPC comes in when I try this using strings.
For some reason, FPC treats the binary mode of the file as a license to
treat each item written to it as a binary blob as well, and this breaks
tp functionality.
For example.
Let's say I have a 5 byte string:
st1 := '12345';
Now, if I blockwrite this to the file under tp:
blockwrite(f1,st1);
The 1 for blocksize wasn't necessary, because tp already knows the
blocks are of size 1 due to the reset command.
Now, if you were to open that text file in an editor, you would see
12345 as the first five bytes of the file (assuming I'd not moved the
file pointer elsewhere first).
Interestingly enough, with FPC, it actually writes 6 bites, (and the
blockcount is necessary).
blockwrite(f1,st1,6);
The reason it needs the extra byte is because the byte 0 (the one that
stores the size of the string) is also written to the file. TP did not
behave this way, though I don't know about delphi, though I'd doubt it dit.
It is fixable, one can simply return to the initial write location and
write a space character to remove the offending character.
However, this doesn't account for long strings (haven't tested to see
what happens in that case)
or other structures that might have additional overhead.
I would expect FPC to write just the structure elements, not the
housekeeping bytes that go along with them when doing a blockwrite.
Is this a bug, or is this a deliberate design decision, and if so, can
we talk about changing it's behavior?
The other issue I encountered while performing this test is when
converting between strings and numbers, FPC does not follow TP
functionality either. That one at least is documented, so I was able to
see why it did things the way it did. However, this too, I think should
be changed to behave as tp did, in that it simply ignored nonnumeric
characters in the string, instead of aborting processing.
At the very least, it should go ahead and convert the numbers it did get
before encountering a nonnumeric value instead of aborting the whole
conversion attempt.
This can be demonstrated by something like this:
st1 := '123';
val(st,number,code);
(this produces a value in number of 123 as it should).
But, when one does:
st1 := #49+#50+#51+#13;
then the same code:
val(st,number,code);
produces an error, and code has the value of 4, (the place in the string
where the error occurred), but number has a value of 0.
In tp, number would still have a value of 123, because it would simply
ignore the carriage return at the end of the string.
I'm sure this one is by design (at least the not ignoring other
charaters part, probably not the skipping assigning a value entirely
part), but it would be helpful if it were modified to simply ignore all
nonnumeric characters in the conversion string, the way tp handled it.
Comments?
I've built in workarounds in my program to solve both of these issues,
but it'd be nice if I didn't have to do that.
More information about the fpc-pascal
mailing list