[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