Recent

Author Topic: In fpcsrc, many places can use StartsStr/StartsText  (Read 1081 times)

AlexTP

  • Hero Member
  • *****
  • Posts: 2649
    • UVviewsoft
In fpcsrc, many places can use StartsStr/StartsText
« on: November 13, 2025, 12:46:40 pm »
I did the search using regex (regex is visible in the report on 1st line). All these places can use StartsStr. the only minus is that StartsStr is in the StrUtils unit...

I don't post this trivial issue to the bugtracker.

Code: [Select]
+Search "copy\(.+?\s*,\s*1\s*,\s*\d+\s*\)\s*=\s*'". Report with [styles].
<compiler\aggas.pas>: #1
< 349>:         if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
<compiler\cmsgs.pas>: #1
< 247>:         else if (Length(s)>11) and (Copy(s,1,11)='# CodePage ') then
<compiler\dirparse.pas>: #3
< 122>:           if Copy(tok,1,2)='NO' then
< 168>:           if Copy(tok,1,2)='NO' then
< 221>:           if Copy(tok,1,2)='NO' then
<compiler\globals.pas>: #1
<1324>:         if Copy(S,1,2)='NO' then
<compiler\link.pas>: #1
<1173>:         if copy(ExtractFileName(para),1,6)='libimp' then
<compiler\ogbase.pas>: #3
<2493>:                           if Copy(hs,1,5)='VTREF' then
<2499>:                           else if Copy(hs,1,7)='VTENTRY' then
<2501>:                           else if Copy(hs,1,9)='VTINHERIT' then
<compiler\ogelf.pas>: #1
< 573>:             if (atype=sec_fpc) and (Copy(aname,1,3)='res') then
<compiler\ognlm.pas>: #1
< 357>:     if (s = '.data') or (copy(s,1,4)='.bss') then result := Section_data else
<compiler\pkgutil.pas>: #1
< 410>:                    if copy(s,1,3)='lib' then
<compiler\arm\raarmgas.pas>: #1
<1400>:                 if copy(hs,1,2) = '.W' then
<compiler\avr\raavrgas.pas>: #1
< 641>:         if ((copy(hs,1,2)='BR') and (length(hs)=4)) then
<compiler\systems\t_emx.pas>: #1
< 297>:     if profile_flag and not (copy(func,1,4)='_16_') then
<compiler\systems\t_nwm.pas>: #2
< 677>:             if copy(option,1,1)='@' then
< 728>:             if copy(option,1,1)='@' then
<compiler\systems\t_os2.pas>: #2
< 298>:     if profile_flag and not (copy(func,1,4)='_16_') then
< 300>:     if profile_flag and not (copy(tmp2,1,4)='_16_') then
<compiler\utils\msg2inc.pp>: #1
< 156>:         else if (Length(s)>11) and (Copy(s,1,11)='# CodePage ') then
<compiler\utils\ppumove.pp>: #2
< 401>:                if copy(s,1,3)='lib' then
< 405>:                if copy(s,1,3)='lib' then
<compiler\utils\ppuutils\ppudump.pp>: #1
<4980>:   while copy(paramstr(startpara),1,1)='-' do
<installer\install.pas>: #2
<1440>:                   if copy(package[i].zip,1,3)='ide' then
<1442>:                   if copy(package[i].zip,1,7)='doc-htm' then
<packages\cdrom\src\fpcddb.pp>: #3
< 471>:             else if (Copy(L,1,6)='TTITLE') then
< 480>:             else if (Copy(L,1,6)='EXTT') then
< 487>:             else if (Copy(L,1,9)='PLAYORDER') then
<packages\fcl-base\src\gettext.pp>: #3
< 302>:     if (Copy(Buffer,1,3)='CHS') or (Copy(Buffer,1,3)='CHT') then FallbackLang:='zh';
< 311>:     if (Copy(Buffer,1,3)='CHN') then Country:='CN'; 
<packages\fcl-db\examples\sqlshell.pas>: #1
< 196>:       if Copy(S,1,1)='\' then
<packages\fcl-db\src\sqldb\interbase\ibconnection.pp>: #1
< 298>:   Result:=(Copy(LS,1,7)='version') and (Length(LS)=8);
<packages\fcl-js\tests\tcscanner.pp>: #1
< 813>:     If (Copy(V,1,2)='0x') then
<packages\fcl-passrc\src\pscanner.pp>: #2
<4811>:         if Copy(CurTokenString,1,1)='$' then
<5131>:       if (Copy(CurTokenString,1,1)='$') then
<packages\fcl-pdf\src\fppdfobjects.pp>: #1
<2965>:   If not (Copy(Value,1,2)='D:') then
<packages\fcl-report\src\fplazreport.pp>: #2
< 286>:     if copy(tmp,1,1)='P' then
< 306>:       if copy(tmp,1,1)='P' then
<packages\fcl-res\src\coffreader.pp>: #1
<  72>:     Result:=copy(s,1,6)='.rsrc$';
<packages\fcl-res\src\rcparserfn.inc>: #3
< 128>:   if Copy(s, 1, 2) = '0x' then
< 130>:   if Copy(s, 1, 2) = '0o' then
< 132>:   if Copy(s, 1, 1) = '0' then
<packages\fcl-web\src\base\custfcgi.pp>: #1
< 348>:       if (V=hvPathInfo) and (Copy(Value,1,2)='//') then //mod_proxy_fcgi gives double slashes at the beginning for some reason
<packages\fcl-web\src\restbridge\sqldbrestdata.pp>: #1
< 529>:   if Copy(CT,1,5)='mysql' then
<packages\fpgtk\src\def\objectdef.pp>: #4
<1058>:       else if copy(PascalType,1,4) = 'pgtk' then
<1077>:     else if copy(PascalType,1,4)='pgtk' then
<1096>:       if (copy(variable,1,4)='gtk.') and
<1104>:       if (copy(variable,1,4)='gtk.') and
<packages\fppkg\src\pkgoptions.pp>: #1
< 843>:         if (Copy(s, 1, 1) = '[') and (Copy(s, length(s), 1) = ']') then
<packages\fv\src\stddlg.pas>: #1
<1309>:         if (S<>'') and (Copy(Dir,1,3)='..'+DirSeparator) then
<packages\gdbint\src\gdbcon.pp>: #1
< 385>:   if copy(RegValueStr,1,2)='0x' then
<packages\ide\fpswitch.pas>: #1
<1048>:       if (Copy(s,1,7)='#IFDEF ') then
<packages\ide\fpsymbol.pas>: #1
< 433>:         if (copy(S,1,1)='_') and (Pos('$$',S)>0) then
<packages\ide\fptools.pas>: #1
<1320>:         if copy(WordS,1,1)='$' then
<packages\ide\fpusrscr.pas>: #3
< 765>:       if ((Copy(ThisTTY, 1, 8) = '/dev/tty') and (ThisTTY[9]<>'p')) or (Copy(ThisTTY,1,8)='/dev/vc/') Then
< 787>:      If Copy(GetEnv('TERM'),1,6)='cons25' Then
<packages\ide\fpviews.pas>: #2
<2840>:       if copy(line,1,3)='=> ' then
<2850>:           if copy(curaddress,1,2)='0x' then
<packages\ide\wchmhwrap.pas>: #2
<  63>:   while (length(relpath)>0) and (copy(relpath,1,3)='../') do
< 292>:   if copy(href,1,7)='ms-its:' then
<packages\ide\whtml.pas>: #2
< 404>:   if copy(Name,1,1)='#' then
< 561>:   if copy(Tag,1,1)='<' then Delete(Tag,1,1);
<packages\ide\whtmlhlp.pas>: #2
<1349>:  if copy(relative,1,6)='http:/' then // external links don't need to be fixed since we can't load them.
<1368>:   if copy(href,1,7)='ms-its:' then
<packages\ide\wini.pas>: #1
< 449>:       if copy(TS,1,1)='[' then
<packages\pastojs\src\pas2jscompiler.pp>: #1
<3530>:     Result:=copy(aValue,1,3)='cmd';
<packages\ptc\src\dos\vga\vgaconsolei.inc>: #1
< 108>:   if (System.Copy(_option, 1, 8) = 'FAKEMODE') and (Length(_option) = 10) and
<packages\ptc\src\win32\directx\win32directxconsolei.inc>: #4
< 167>:   if System.Copy(AOption, 1, 13) = 'default width' then
< 180>:   if System.Copy(AOption, 1, 14) = 'default height' then
< 193>:   if System.Copy(AOption, 1, 12) = 'default bits' then
< 309>:   if System.Copy(AOption, 1, 9) = 'frequency' then
<packages\rtl-console\src\unix\keyboard.pp>: #3
<1209>:   if copy(fpgetenv('TERM'),1,4)='cons' then
<1471>:       if copy(fpgetenv('TERM'),1,5)='xterm' then
<1493>:   if copy(fpgetenv('TERM'),1,5)='xterm' then
<packages\rtl-console\src\unix\video.pp>: #1
<1106>:      if copy(ThisTTY, 1, 9) = '/dev/ttyv' then  {FreeBSD has these}
<packages\users\examples\testpass.pp>: #1
<  66>:   If Copy(EncPass,1,3) = '$1$' then
<packages\vcl-compat\src\system.ioutils.pp>: #1
< 614>:   if (Length(aPath)>=3) and (Copy(aPath,1,2)='//') then
<packages\winunits-base\src\typelib.pas>: #3
< 326>:     if (copy(typename,1,3)='tag') then
< 328>:     else if (copy(typename,1,4)='_tag') then
< 330>:     else if (copy(typename,1,5)='__tag') then
<rtl\go32v2\system.pp>: #1
< 393>:         if Copy(proxy_s,1,7)=' !proxy' then
<rtl\watcom\system.pp>: #1
< 339>:         if Copy(proxy_s,1,7)=' !proxy' then
<tests\utils\dbconfig.pp>: #1
< 360>:         if (copy(O,1,2)='--') then
<tests\utils\dbdigest.pp>: #3
< 357>:         if (copy(O,1,2)='--') then
< 508>:   if not FileExists(FN) and (Copy(FN,1,3)='../') then
< 529>:   if not FileExists(FN) and (Copy(FN,1,3)='../') then
<tests\utils\avx\cmpoptions.pas>: #3
<  75>:     if copy(ParamStr(i), 1, 1) = '-' then
<  86>:                 if copy(FSourceMask, 1, 2) = '\\' then FSourceMask := ExpandUNCFileName(FSourceMask)
<  98>:                 if copy(FDestPath, 1, 2) = '\\' then FDestPath := ExpandUNCFileName(FDestPath)
<tests\utils\avx\options.pas>: #1
<  76>:     if copy(ParamStr(i), 1, 1) = '-' then
<tests\utils\dosbox\dosbox_wrapper.pas>: #1
< 618>:       if (paramcount>1) and (copy(paramstr(2),1,2)='-S') then
<utils\ppdep.pp>: #5
< 420>:                     if (Copy(hs^,1,4)='USES') and ((length(hs^)=4) or (hs^[5] in [' ',#9])) then
< 430>:                         if (Copy(hs^,1,7)='PROGRAM') then
< 436>:                          if InImplementation and ((copy(hs^,1,5)='CONST') or
< 437>:                             (copy(hs^,1,3)='VAR') or (copy(hs^,1,5)='BEGIN')) then
<utils\fpcres\paramparser.pas>: #2
< 368>:   if copy(s,1,1)='-' then Result:=true;
< 423>:         if copy(tmp,1,1)='@' then
<utils\fpcreslipo\paramparser.pp>: #1
< 120>:   if copy(s,1,1)='-' then Result:=true;
<utils\fpdoc\dwriter.pp>: #1
< 364>:     (Copy(AMember.Name, 1, 2) = 'On');
<utils\fpdoc\dw_chm.pp>: #1
< 799>:     if copy(ALinkPrefix,1,2)='..' then // workaround for project files.
<utils\fpdoc\fpclasschart.pp>: #1
< 667>:     if Copy(FileName, 1, 1) = '@' then
<utils\fpdoc\fpdoc.pp>: #3
< 211>:     Result:=(Copy(s,1,3)='-p=') or (Copy(s,1,Length(SOptProject))=SOptProject) or (Copy(s,1,Length(SOptMacro))=SOptMacro);
< 217>:     Result:=((Copy(s,1,3)='-a=') or (Copy(s,1,Length(SOptPackage))=SOptPackage));
< 296>:     if Copy(FileName, 1, 1) = '@' then
<utils\fpdoc\makeskel.pp>: #1
< 509>:     if Copy(FileName, 1, 1) = '@' then
<utils\h2pas\scan.pas>: #1
< 646>:                            if copy(yytext,1,2)='0x' then
<utils\instantfpc\instantfpc.pas>: #2
< 119>:   else if copy(p,1,11)='--compiler=' then
< 124>:   else if copy(p,1,12)='--set-cache=' then
<utils\instantfpc\instantfptools.pas>: #2
< 363>:     if (Copy(p,1,1)='-') and (copy(p,1,2)<>'--') then
< 373>:   While (I<=ParamCount) and (Copy(ParamStr(i),1,1)='-') do
<utils\pas2jni\pas2jni.pas>: #2
<  54>:   if Copy(p, 1, 1) = '@' then begin
<  85>:     if Copy(s, 1, 1) = '-' then begin
<utils\pas2jni\ppuparser.pas>: #1
< 407>:         if Copy(d.Name, 1, 1) = '$' then
<utils\pas2jni\writer.pas>: #1
<1352>:     if Copy(d.Value, 1, 1) = '"' then
<utils\pas2js\webidl2pas.pp>: #1
< 142>:   if (Copy(A,1,1)='@') then
<utils\tply\plex.pas>: #1
< 630>:     if copy(paramStr(i), 1, 1)='-' then
<utils\tply\pyacc.pas>: #1
<2406>:     if copy(paramStr(i), 1, 1)='-' then

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12563
  • FPC developer.
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #1 on: November 13, 2025, 01:37:41 pm »
And strutils is in packages/rtl-objpas and not yet compiled when the compiler compiles itself.

AlexTP

  • Hero Member
  • *****
  • Posts: 2649
    • UVviewsoft
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #2 on: November 13, 2025, 08:52:31 pm »
Ok, you cannot use StrUtils, but you can make a tiny unit with StartsStr and use it in the compiler?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12563
  • FPC developer.
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #3 on: November 13, 2025, 09:13:38 pm »
I assume it could be added to cutils. I'm not a compiler dev, please file a bug.

PascalDragon

  • Hero Member
  • *****
  • Posts: 6230
  • Compiler Developer
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #4 on: November 13, 2025, 09:25:03 pm »
Even if StrUtils would be usable in the compiler this function would not be usable, because the compiler uses predominantly ShortString and not AnsiString and thus calling the AnsiString-based StartsStr would lead to unnecessary conversions from/to ShortString (this is something that a simple search can not discover).

AlexTP

  • Hero Member
  • *****
  • Posts: 2649
    • UVviewsoft
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #5 on: November 13, 2025, 09:50:09 pm »
Ok, then some replacements for StartsStr must be defined, eg in the 'cutils', for the ShortString.

avk

  • Hero Member
  • *****
  • Posts: 825
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #6 on: November 13, 2025, 10:20:12 pm »
Even if StrUtils would be usable in the compiler this function would not be usable, because the compiler uses predominantly ShortString and not AnsiString and thus calling the AnsiString-based StartsStr would lead to unnecessary conversions from/to ShortString (this is something that a simple search can not discover).

What about such function
Code: Pascal  [Select][+][-]
  1. function SameChars(const L, R: array of AnsiChar): Boolean;
  2. begin
  3.   if Length(L) <> Length(R) then exit(False);
  4.   if Length(L) = 0 then exit(True);
  5.   Result := CompareByte(L[0], R[0], Length(L)) = 0;
  6. end;
  7.  

PascalDragon

  • Hero Member
  • *****
  • Posts: 6230
  • Compiler Developer
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #7 on: November 13, 2025, 10:35:49 pm »
  • ShortString can not be passed to array of AnsiChar
  • Your function still means that Copy needs to be used, so you're essentially replacing the =-operator with a function call

avk

  • Hero Member
  • *****
  • Posts: 825
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #8 on: November 13, 2025, 11:02:44 pm »
I meant
Code: Pascal  [Select][+][-]
  1. program char_arr_test;
  2. {$mode objfpc}
  3.  
  4. function SameChars(const L, R: array of AnsiChar): Boolean;
  5. begin
  6.   if Length(L) <> Length(R) then exit(False);
  7.   if Length(L) = 0 then exit(True);
  8.   Result := CompareByte(L[0], R[0], Length(L)) = 0;
  9. end;
  10.  
  11. var
  12.   s: string;
  13. begin
  14.   s := 'abcdefgh';
  15.   WriteLn(SameChars(s[3..8], 'cdefgh'));
  16. end.
  17.  

code that FPC generated to call the function
Code: ASM  [Select][+][-]
  1. # [16] WriteLn(SameChars(s[3..8], 'cdefgh'));
  2.         call    fpc_get_output
  3.         movq    %rax,%rbx
  4.         leaq    U_$P$CHAR_ARR_TEST_$$_S+3(%rip),%rcx
  5.         leaq    .Ld2(%rip),%r8
  6.         movl    $5,%r9d
  7.         movl    $5,%edx
  8.         call    P$CHAR_ARR_TEST_$$_SAMECHARS$array_of_ANSICHAR$array_of_ANSICHAR$$BOOLEAN
  9.         movb    %al,%r8b
  10.         movq    %rbx,%rdx
  11.         xorl    %ecx,%ecx
  12.         call    fpc_write_text_boolean
  13.         call    fpc_iocheck
  14.         movq    %rbx,%rcx
  15.         call    fpc_writeln_end
  16.         call    fpc_iocheck
  17.  

There doesn't seem to be any copying.

Khrys

  • Sr. Member
  • ****
  • Posts: 366
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #9 on: November 14, 2025, 06:48:40 am »
Why though? To improve readability?

I do think that  StartsStr(hs,'VTREF')  is more readable than  Copy(hs,1,5)='VTREF',  but ultimately it's up to the compiler devs.

cdbc

  • Hero Member
  • *****
  • Posts: 2509
    • http://www.cdbc.dk
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #10 on: November 14, 2025, 07:02:20 am »
Hi
My 2 cents worth:
"Why would you want to add an abstraction-layer in a place, where speed counts the most"?!?
...I wouldn't!
In the compiler it's just "Get up and go"  ...no need for syntactic sugar!!!
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

Khrys

  • Sr. Member
  • ****
  • Posts: 366
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #11 on: November 14, 2025, 08:40:00 am »
Hi
My 2 cents worth:
"Why would you want to add an abstraction-layer in a place, where speed counts the most"?!?
...I wouldn't!
In the compiler it's just "Get up and go"  ...no need for syntactic sugar!!!
Regards Benny

But  Copy()  creates, well, a copy of the relevant string part and only then does a comparison, while  StartsStr  skips the copying part and does just the comparison - this isn't just syntactic sugar.

Thaddy

  • Hero Member
  • *****
  • Posts: 18493
  • Here stood a man who saw the Elbe and jumped it.
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #12 on: November 14, 2025, 09:41:38 am »
Doesn't what avk shows contradict this? Btw, his code is repeatable.
« Last Edit: November 14, 2025, 10:21:29 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

BrunoK

  • Hero Member
  • *****
  • Posts: 747
  • Retired programmer
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #13 on: November 14, 2025, 03:54:40 pm »
  • ShortString can not be passed to array of AnsiChar
  • Your function still means that Copy needs to be used, so you're essentially replacing the =-operator with a function call
So what about :
Code: Pascal  [Select][+][-]
  1. program char_arr_test;
  2.   {$mode objfpc}
  3.  
  4.   function SameChars(const L, R: array of ansichar): boolean;
  5.   begin
  6.     if Length(L) <> Length(R) then exit(False);
  7.     if Length(L) = 0 then exit(True);
  8.     Result := CompareByte(L[0], R[0], Length(L)) = 0;
  9.   end;
  10.  
  11. var
  12.   s, s1: string;
  13.   ss, ss1: shortstring;
  14.   lAreSame: boolean;
  15. begin
  16.   s := 'abcdefgh';
  17.   s1 := 'cdefg';
  18.   s := s + 'i';
  19.   s1 := s1 + 'h';
  20.   asm      NOP end;
  21.   lAreSame := SameChars(s[3..8], s1[1..6]);
  22.   // lea r8,[rip+$00010A46]    # $0000000100012111
  23.   // lea rcx,[rip+$00010941]    # $0000000100012013
  24.   // mov r9d,$00000005
  25.   // mov edx,$00000005
  26.   // call -$00000112    # $00000001000015D0 SameChars project1.lpr:5
  27.   // mov [rip+$00010D28],al
  28.   asm      NOP end;
  29.   WriteLn(lAreSame);
  30.  
  31.   ss := s;    // shortstring
  32.   ss1 := s1;  // shortstring
  33.   asm      NOP end;
  34.   lAreSame := SameChars(ss[3..8], ss1[1..6]);
  35.   // lea r8,[rip+$00010BC5]    # $0000000100012311
  36.   // lea rcx,[rip+$00010AC0]    # $0000000100012213
  37.   // mov r9d,$00000005
  38.   // mov edx,$00000005
  39.   // call -$00000193    # $00000001000015D0 SameChars project1.lpr:5
  40.   // mov [rip+$00010CA7],al
  41.   asm      NOP end;
  42.   WriteLn(lAreSame);
  43.  
  44.   ReadLn;
  45. end.

It compiles and give correct result without any copy generated in the assembler code.

AlexTP

  • Hero Member
  • *****
  • Posts: 2649
    • UVviewsoft
Re: In fpcsrc, many places can use StartsStr/StartsText
« Reply #14 on: November 14, 2025, 04:52:58 pm »
Instead of
  lAreSame := SameChars(s[3..8], s1[1..6]);

can we avoid indexes over vars? To keep code more readable.
this is ugly:
  lAreSame := SameChars(prefix[1..Length(prefix)], s1[1..Length(prefix)]);
« Last Edit: November 14, 2025, 05:07:24 pm by AlexTP »

 

TinyPortal © 2005-2018