With FP/Lazarus
// asm mode: intel
asm
//...
CALL @fpc_ansistr_setlength
//...
end;
it should work, but actually not, it gives: "Error: Unknown label identifier @FPC_ANSISTR_SETLENGTH"
I have no clue about what's going on at this moment. Any help will be appreciated.
With FP/Lazarus
// asm mode: intel
asm
//...
CALL @fpc_ansistr_setlength
//...
end;
it should work, but actually not, it gives: "Error: Unknown label identifier @FPC_ANSISTR_SETLENGTH"
I have no clue about what's going on at this moment. Any help will be appreciated.
You need to reimport the procedure and then call that:
Procedure fpc_AnsiStr_SetLength (Var S : RawByteString; l : SizeInt{$ifdef FPC_HAS_CPSTRING}; cp : TSystemCodePage{$endif FPC_HAS_CPSTRING});external 'FPC_ANSISTR_SETLENGTH'; procedure Test; begin asm call fpc_ansistr_setlength end; end;
I have tried it as you mentioned (with a slight modification as I still using the good old FP 2.6.4):
procedure fpc_AnsiStr_SetLength (Var S: AnsiString; l: SizeInt{$ifdef FPC_HAS_CPSTRING};cp: TSystemCodePage{$endif FPC_HAS_CPSTRING}); external 'FPC_ANSISTR_SETLENGTH';
I have tried it as you mentioned (with a slight modification as I still using the good old FP 2.6.4):
procedure fpc_AnsiStr_SetLength (Var S: AnsiString; l: SizeInt{$ifdef FPC_HAS_CPSTRING};cp: TSystemCodePage{$endif FPC_HAS_CPSTRING}); external 'FPC_ANSISTR_SETLENGTH';
Ah, sorry, I meant external name 'FPC_ANSISTR_SETLENGTH'.
But I'd head Jonas' advice as well: write your own function that calls SetLength.
I am not planning to use any new version of FPC, because 3.0.4 generated code is erratic, so I think I can kindly ignore the latter advices.
I am not planning to use any new version of FPC, because 3.0.4 generated code is erratic, so I think I can kindly ignore the latter advices.
In how far is it erratic? Do you have an example? If we don't know about it, we can't fix it. Though you could also test whether 3.2 solves it.
You say that you managed to locate it. Is it wrongly generated assembly code? Does it occur only on specific platforms? Does it only occur with specific optimization settings? Is the function inlined? Are generics involved? Did the problems also occur with 3.0.2 or 3.0.0?
Maybe indeed do a test with 3.2, many things were fixed in the code generator and parser. You could maybe also do a test with 3.3.1.
You say that you managed to locate it. Is it wrongly generated assembly code? Does it occur only on specific platforms? Does it only occur with specific optimization settings? Is the function inlined? Are generics involved? Did the problems also occur with 3.0.2 or 3.0.0?
Maybe indeed do a test with 3.2, many things were fixed in the code generator and parser. You could maybe also do a test with 3.3.1.
#176 is not a valid UTF8 character.
You should try RawByteString instead of String!
In your example, s[2] (a single character) could give a different result than Copy(s,2,1) (an Utf8 string).
You can't compare an incorrectly encoded string to a correctly encoded UTF8 string constant.
The character #176 as UTF8-string is not that single character #176, but its UTF8 encoded representation! Therefore the comparison fails.
There is nothing arbitrary about this. The code page aware AnsiString type was the big feature (and change) in FPC 3.0.0 (see here (https://wiki.freepascal.org/User_Changes_3.0#AnsiStrings_are_now_codepage-aware) which also references this (https://wiki.freepascal.org/FPC_Unicode_support)). The FPC RTL itself initializes with the code page of the operating system, but Lazarus forces this to be UTF-8 (see here (https://wiki.freepascal.org/Unicode_Support_in_Lazarus)), thus why you don't have any problem with a command line application, but see this issue with a LCL GUI application.
To better explain where your problem is:
s:='('+#176+')'; Result:=Copy(s, 2, 1)=#176;
The string constant at the right side of the assignment to s is in your system's code page. Due to the LCL's setting of using UTF-8 by default the assignment will convert the string to UTF-8 (you can see this by using Length(s), it will return a value > 3). Thus the following Copy will extract only a part of the UTF-8 character for #176, thus the comparison will fail.
There is nothing arbitrary about this. The code page aware AnsiString type was the big feature (and change) in FPC 3.0.0 (see here (https://wiki.freepascal.org/User_Changes_3.0#AnsiStrings_are_now_codepage-aware) which also references this (https://wiki.freepascal.org/FPC_Unicode_support)). The FPC RTL itself initializes with the code page of the operating system, but Lazarus forces this to be UTF-8 (see here (https://wiki.freepascal.org/Unicode_Support_in_Lazarus)), thus why you don't have any problem with a command line application, but see this issue with a LCL GUI application.
To better explain where your problem is:
s:='('+#176+')'; Result:=Copy(s, 2, 1)=#176;
The string constant at the right side of the assignment to s is in your system's code page. Due to the LCL's setting of using UTF-8 by default the assignment will convert the string to UTF-8 (you can see this by using Length(s), it will return a value > 3). Thus the following Copy will extract only a part of the UTF-8 character for #176, thus the comparison will fail.
When implementing a new feature, it should be introduced as an extra option beside the well-known old one, not by replacing it!
I still don't understand, why they blatantly REPLACING something with a totally different incompatible thing, messing up existing codes. :o
When implementing a new feature, it should be introduced as an extra option beside the well-known old one, not by replacing it!
I still don't understand, why they blatantly REPLACING something with a totally different incompatible thing, messing up existing codes. :o
There was no way to implement this optionally. The code page aware string is a base part of the language and the way the LCL simply stuffed UTF-8 characters into AnsiStrings was simply wrong now due to the compiler now automatically inserting conversions between code pages thus leading to corruption of the string data.
Also even if we had made this optional, the new behaviour would have been the default anyway and would you have found out that you'd need to change some hypothetical switch? Considering that you didn't know about the string related changes I assume you would not have. So what use would it have been anyway?