sstrings.inc 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {****************************************************************************
  11. subroutines for string handling
  12. ****************************************************************************}
  13. procedure fpc_Shortstr_SetLength(var s:shortstring;len:SizeInt);[Public,Alias : 'FPC_SHORTSTR_SETLENGTH']; compilerproc;
  14. begin
  15. if Len>255 then
  16. Len:=255;
  17. s[0]:=chr(len);
  18. end;
  19. function fpc_shortstr_copy(const s : shortstring;index : SizeInt;count : SizeInt): shortstring;compilerproc;
  20. begin
  21. if count<0 then
  22. count:=0;
  23. if index>1 then
  24. dec(index)
  25. else
  26. index:=0;
  27. if index>length(s) then
  28. count:=0
  29. else
  30. if count>length(s)-index then
  31. count:=length(s)-index;
  32. fpc_shortstr_Copy[0]:=chr(Count);
  33. Move(s[Index+1],fpc_shortstr_Copy[1],Count);
  34. end;
  35. procedure delete(var s : shortstring;index : SizeInt;count : SizeInt);
  36. begin
  37. if index<=0 then
  38. exit;
  39. if (Index<=Length(s)) and (Count>0) then
  40. begin
  41. if Count>length(s)-Index then
  42. Count:=length(s)-Index+1;
  43. s[0]:=Chr(length(s)-Count);
  44. if Index<=Length(s) then
  45. Move(s[Index+Count],s[Index],Length(s)-Index+1);
  46. end;
  47. end;
  48. procedure insert(const source : shortstring;var s : shortstring;index : SizeInt);
  49. var
  50. cut,srclen,indexlen : SizeInt;
  51. begin
  52. if index<1 then
  53. index:=1;
  54. if index>length(s) then
  55. index:=length(s)+1;
  56. indexlen:=Length(s)-Index+1;
  57. srclen:=length(Source);
  58. if sizeInt(length(source))+sizeint(length(s))>=sizeof(s) then
  59. begin
  60. cut:=sizeInt(length(source))+sizeint(length(s))-sizeof(s)+1;
  61. if cut>indexlen then
  62. begin
  63. dec(srclen,cut-indexlen);
  64. indexlen:=0;
  65. end
  66. else
  67. dec(indexlen,cut);
  68. end;
  69. move(s[Index],s[Index+srclen],indexlen);
  70. move(Source[1],s[Index],srclen);
  71. s[0]:=chr(index+srclen+indexlen-1);
  72. end;
  73. procedure insert(source : Char;var s : shortstring;index : SizeInt);
  74. var
  75. indexlen : SizeInt;
  76. begin
  77. if index<1 then
  78. index:=1;
  79. if index>length(s) then
  80. index:=length(s)+1;
  81. indexlen:=Length(s)-Index+1;
  82. if (sizeint(length(s))+1=sizeof(s)) and (indexlen>0) then
  83. dec(indexlen);
  84. move(s[Index],s[Index+1],indexlen);
  85. s[Index]:=Source;
  86. s[0]:=chr(index+indexlen);
  87. end;
  88. function pos(const substr : shortstring;const s : shortstring):SizeInt;
  89. var
  90. i,MaxLen : SizeInt;
  91. pc : pchar;
  92. begin
  93. Pos:=0;
  94. if Length(SubStr)>0 then
  95. begin
  96. MaxLen:=sizeint(Length(s))-Length(SubStr);
  97. i:=0;
  98. pc:=@s[1];
  99. while (i<=MaxLen) do
  100. begin
  101. inc(i);
  102. if (SubStr[1]=pc^) and
  103. (CompareChar(Substr[1],pc^,Length(SubStr))=0) then
  104. begin
  105. Pos:=i;
  106. exit;
  107. end;
  108. inc(pc);
  109. end;
  110. end;
  111. end;
  112. {Faster when looking for a single char...}
  113. function pos(c:char;const s:shortstring):SizeInt;
  114. var
  115. i : SizeInt;
  116. pc : pchar;
  117. begin
  118. pc:=@s[1];
  119. for i:=1 to length(s) do
  120. begin
  121. if pc^=c then
  122. begin
  123. pos:=i;
  124. exit;
  125. end;
  126. inc(pc);
  127. end;
  128. pos:=0;
  129. end;
  130. function fpc_char_copy(c:char;index : SizeInt;count : SizeInt): shortstring;compilerproc;
  131. begin
  132. if (index=1) and (Count>0) then
  133. fpc_char_Copy:=c
  134. else
  135. fpc_char_Copy:='';
  136. end;
  137. function pos(const substr : shortstring;c:char): SizeInt;
  138. begin
  139. if (length(substr)=1) and (substr[1]=c) then
  140. Pos:=1
  141. else
  142. Pos:=0;
  143. end;
  144. {$ifdef IBM_CHAR_SET}
  145. const
  146. UpCaseTbl : shortstring[7]=#154#142#153#144#128#143#165;
  147. LoCaseTbl : shortstring[7]=#129#132#148#130#135#134#164;
  148. {$endif}
  149. function upcase(c : char) : char;
  150. {$IFDEF IBM_CHAR_SET}
  151. var
  152. i : longint;
  153. {$ENDIF}
  154. begin
  155. if (c in ['a'..'z']) then
  156. upcase:=char(byte(c)-32)
  157. else
  158. {$IFDEF IBM_CHAR_SET}
  159. begin
  160. i:=Pos(c,LoCaseTbl);
  161. if i>0 then
  162. upcase:=UpCaseTbl[i]
  163. else
  164. upcase:=c;
  165. end;
  166. {$ELSE}
  167. upcase:=c;
  168. {$ENDIF}
  169. end;
  170. function upcase(const s : shortstring) : shortstring;
  171. var
  172. i : longint;
  173. begin
  174. upcase[0]:=s[0];
  175. for i := 1 to length (s) do
  176. upcase[i] := upcase (s[i]);
  177. end;
  178. function lowercase(c : char) : char;overload;
  179. {$IFDEF IBM_CHAR_SET}
  180. var
  181. i : longint;
  182. {$ENDIF}
  183. begin
  184. if (c in ['A'..'Z']) then
  185. lowercase:=char(byte(c)+32)
  186. else
  187. {$IFDEF IBM_CHAR_SET}
  188. begin
  189. i:=Pos(c,UpCaseTbl);
  190. if i>0 then
  191. lowercase:=LoCaseTbl[i]
  192. else
  193. lowercase:=c;
  194. end;
  195. {$ELSE}
  196. lowercase:=c;
  197. {$ENDIF}
  198. end;
  199. function lowercase(const s : shortstring) : shortstring; overload;
  200. var
  201. i : longint;
  202. begin
  203. lowercase [0]:=s[0];
  204. for i:=1 to length(s) do
  205. lowercase[i]:=lowercase (s[i]);
  206. end;
  207. const
  208. HexTbl : array[0..15] of char='0123456789ABCDEF';
  209. function hexstr(val : longint;cnt : byte) : shortstring;
  210. var
  211. i : longint;
  212. begin
  213. hexstr[0]:=char(cnt);
  214. for i:=cnt downto 1 do
  215. begin
  216. hexstr[i]:=hextbl[val and $f];
  217. val:=val shr 4;
  218. end;
  219. end;
  220. function octstr(val : longint;cnt : byte) : shortstring;
  221. var
  222. i : longint;
  223. begin
  224. octstr[0]:=char(cnt);
  225. for i:=cnt downto 1 do
  226. begin
  227. octstr[i]:=hextbl[val and 7];
  228. val:=val shr 3;
  229. end;
  230. end;
  231. function binstr(val : longint;cnt : byte) : shortstring;
  232. var
  233. i : longint;
  234. begin
  235. binstr[0]:=char(cnt);
  236. for i:=cnt downto 1 do
  237. begin
  238. binstr[i]:=char(48+val and 1);
  239. val:=val shr 1;
  240. end;
  241. end;
  242. function hexstr(val : int64;cnt : byte) : shortstring;
  243. var
  244. i : longint;
  245. begin
  246. hexstr[0]:=char(cnt);
  247. for i:=cnt downto 1 do
  248. begin
  249. hexstr[i]:=hextbl[val and $f];
  250. val:=val shr 4;
  251. end;
  252. end;
  253. function octstr(val : int64;cnt : byte) : shortstring;
  254. var
  255. i : longint;
  256. begin
  257. octstr[0]:=char(cnt);
  258. for i:=cnt downto 1 do
  259. begin
  260. octstr[i]:=hextbl[val and 7];
  261. val:=val shr 3;
  262. end;
  263. end;
  264. function binstr(val : int64;cnt : byte) : shortstring;
  265. var
  266. i : longint;
  267. begin
  268. binstr[0]:=char(cnt);
  269. for i:=cnt downto 1 do
  270. begin
  271. binstr[i]:=char(48+val and 1);
  272. val:=val shr 1;
  273. end;
  274. end;
  275. Function hexStr(Val:qword;cnt:byte):shortstring;
  276. begin
  277. hexStr:=hexStr(int64(Val),cnt);
  278. end;
  279. Function OctStr(Val:qword;cnt:byte):shortstring;
  280. begin
  281. OctStr:=OctStr(int64(Val),cnt);
  282. end;
  283. Function binStr(Val:qword;cnt:byte):shortstring;
  284. begin
  285. binStr:=binStr(int64(Val),cnt);
  286. end;
  287. function hexstr(val : pointer) : shortstring;
  288. var
  289. i : longint;
  290. v : ptruint;
  291. begin
  292. v:=ptruint(val);
  293. hexstr[0]:=chr(sizeof(pointer)*2);
  294. for i:=sizeof(pointer)*2 downto 1 do
  295. begin
  296. hexstr[i]:=hextbl[v and $f];
  297. v:=v shr 4;
  298. end;
  299. end;
  300. function space (b : byte): shortstring;
  301. begin
  302. space[0] := chr(b);
  303. FillChar (Space[1],b,' ');
  304. end;
  305. {*****************************************************************************
  306. Str() Helpers
  307. *****************************************************************************}
  308. procedure fpc_shortstr_SInt(v : valSInt;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_SINT']; compilerproc;
  309. begin
  310. int_str(v,s);
  311. if length(s)<len then
  312. s:=space(len-length(s))+s;
  313. end;
  314. procedure fpc_shortstr_UInt(v : valUInt;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_UINT']; compilerproc;
  315. begin
  316. int_str(v,s);
  317. if length(s)<len then
  318. s:=space(len-length(s))+s;
  319. end;
  320. {$ifndef CPU64}
  321. procedure fpc_shortstr_qword(v : qword;len : longint;out s : shortstring);[public,alias:'FPC_SHORTSTR_QWORD']; compilerproc;
  322. begin
  323. int_str(v,s);
  324. if length(s)<len then
  325. s:=space(len-length(s))+s;
  326. end;
  327. procedure fpc_shortstr_int64(v : int64;len : longint;out s : shortstring);[public,alias:'FPC_SHORTSTR_INT64']; compilerproc;
  328. begin
  329. int_str(v,s);
  330. if length(s)<len then
  331. s:=space(len-length(s))+s;
  332. end;
  333. {$endif CPU64}
  334. { fpc_shortstr_sInt must appear before this file is included, because }
  335. { it's used inside real2str.inc and otherwise the searching via the }
  336. { compilerproc name will fail (JM) }
  337. {$ifndef FPUNONE}
  338. {$I real2str.inc}
  339. {$endif}
  340. {$ifndef FPUNONE}
  341. procedure fpc_shortstr_float(d : ValReal;len,fr,rt : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT']; compilerproc;
  342. begin
  343. str_real(len,fr,d,treal_type(rt),s);
  344. end;
  345. {$endif}
  346. function fpc_shortstr_enum_intern(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring): longint;
  347. type
  348. Ptypeinfo=^Ttypeinfo;
  349. Ttypeinfo=record
  350. kind:byte;
  351. name:shortstring;
  352. end;
  353. Penuminfo=^Tenuminfo;
  354. Tenuminfo={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  355. ordtype:byte;
  356. minvalue,maxvalue:longint;
  357. basetype:pointer;
  358. namelist:shortstring;
  359. end;
  360. Tsorted_array={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  361. o:longint;
  362. s:Pstring;
  363. end;
  364. var
  365. p:Pstring;
  366. l,h,m:cardinal;
  367. sorted_array:^Tsorted_array;
  368. i,spaces:byte;
  369. begin
  370. fpc_shortstr_enum_intern:=107;
  371. if Pcardinal(ord2strindex)^=0 then
  372. begin
  373. {The compiler did generate a lookup table.}
  374. with Penuminfo(Pbyte(typinfo)+2+length(Ptypeinfo(typinfo)^.name))^ do
  375. begin
  376. if (ordinal<minvalue) or (ordinal>maxvalue) then
  377. exit; {Invalid ordinal value for this enum.}
  378. dec(ordinal,minvalue);
  379. end;
  380. {Get the address of the string.}
  381. p:=Pshortstring((PPpointer(ord2strindex+sizeof(longint))+ordinal)^);
  382. if p=nil then
  383. exit; {Invalid ordinal value for this enum.}
  384. s:=p^;
  385. end
  386. else
  387. begin
  388. {The compiler did generate a sorted array of (ordvalue,Pstring) tuples.}
  389. sorted_array:=pointer(Pcardinal(ord2strindex)+2);
  390. {Use a binary search to get the string.}
  391. l:=0;
  392. h:=(Pcardinal(ord2strindex)+1)^-1;
  393. repeat
  394. m:=(l+h) div 2;
  395. if ordinal>sorted_array[m].o then
  396. l:=m+1
  397. else if ordinal<sorted_array[m].o then
  398. h:=m-1
  399. else
  400. break;
  401. if l>h then
  402. exit; {Ordinal value not found? Kaboom.}
  403. until false;
  404. s:=sorted_array[m].s^;
  405. end;
  406. {Pad the string with spaces if necessary.}
  407. if len>length(s) then
  408. begin
  409. spaces:=len-length(s);
  410. for i:=1 to spaces do
  411. s[length(s)+i]:=' ';
  412. inc(byte(s[0]),spaces);
  413. end;
  414. fpc_shortstr_enum_intern:=0;
  415. end;
  416. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);[public,alias:'FPC_SHORTSTR_ENUM'];compilerproc;
  417. var
  418. res: longint;
  419. begin
  420. res:=fpc_shortstr_enum_intern(ordinal,len,typinfo,ord2strindex,s);
  421. if (res<>0) then
  422. runerror(107);
  423. end;
  424. { also define alias for internal use in the system unit }
  425. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);external name 'FPC_SHORTSTR_ENUM';
  426. procedure fpc_shortstr_currency(c : currency; len,f : SizeInt; out s : shortstring);[public,alias:'FPC_SHORTSTR_CURRENCY']; compilerproc;
  427. const
  428. MinLen = 8; { Minimal string length in scientific format }
  429. var
  430. buf : array[1..19] of char;
  431. i,j,k,reslen,tlen,sign,r,point : longint;
  432. ic : qword;
  433. begin
  434. { default value for length is -32767 }
  435. if len=-32767 then
  436. len:=25;
  437. if PInt64(@c)^ >= 0 then
  438. begin
  439. ic:=QWord(PInt64(@c)^);
  440. sign:=0;
  441. end
  442. else
  443. begin
  444. sign:=1;
  445. ic:=QWord(-PInt64(@c)^);
  446. end;
  447. { converting to integer string }
  448. tlen:=0;
  449. repeat
  450. Inc(tlen);
  451. buf[tlen]:=Chr(ic mod 10 + $30);
  452. ic:=ic div 10;
  453. until ic = 0;
  454. { calculating:
  455. reslen - length of result string,
  456. r - rounding or appending zeroes,
  457. point - place of decimal point }
  458. reslen:=tlen;
  459. if f <> 0 then
  460. Inc(reslen); { adding decimal point length }
  461. if f < 0 then
  462. begin
  463. { scientific format }
  464. Inc(reslen,5); { adding length of sign and exponent }
  465. if len < MinLen then
  466. len:=MinLen;
  467. r:=reslen-len;
  468. if reslen < len then
  469. reslen:=len;
  470. if r > 0 then
  471. begin
  472. reslen:=len;
  473. point:=tlen - r;
  474. end
  475. else
  476. point:=tlen;
  477. end
  478. else
  479. begin
  480. { fixed format }
  481. Inc(reslen, sign);
  482. { prepending fractional part with zeroes }
  483. while tlen < 5 do
  484. begin
  485. Inc(reslen);
  486. Inc(tlen);
  487. buf[tlen]:='0';
  488. end;
  489. { Currency have 4 digits in fractional part }
  490. r:=4 - f;
  491. point:=f;
  492. if point <> 0 then
  493. begin
  494. if point > 4 then
  495. point:=4;
  496. Inc(point);
  497. end;
  498. Dec(reslen,r);
  499. end;
  500. { rounding string if r > 0 }
  501. if r > 0 then
  502. begin
  503. i:=1;
  504. k:=0;
  505. for j:=0 to r do
  506. begin
  507. if (k=1) and (buf[i]='9') then
  508. buf[i]:='0'
  509. else
  510. begin
  511. buf[i]:=chr(ord(buf[i]) + k);
  512. if buf[i] >= '5' then
  513. k:=1
  514. else
  515. k:=0;
  516. end;
  517. Inc(i);
  518. if i>tlen then
  519. break;
  520. end;
  521. If (k=1) and (buf[i-1]='0') then
  522. buf[i]:=chr(Ord(buf[i])+1);
  523. end;
  524. { preparing result string }
  525. if reslen<len then
  526. reslen:=len;
  527. if reslen>High(s) then
  528. begin
  529. if r < 0 then
  530. Inc(r, reslen - High(s));
  531. reslen:=High(s);
  532. end;
  533. SetLength(s,reslen);
  534. j:=reslen;
  535. if f<0 then
  536. begin
  537. { writing power of 10 part }
  538. if PInt64(@c)^ = 0 then
  539. k:=0
  540. else
  541. k:=tlen-5;
  542. if k >= 0 then
  543. s[j-2]:='+'
  544. else
  545. begin
  546. s[j-2]:='-';
  547. k:=-k;
  548. end;
  549. s[j]:=Chr(k mod 10 + $30);
  550. Dec(j);
  551. s[j]:=Chr(k div 10 + $30);
  552. Dec(j,2);
  553. s[j]:='E';
  554. Dec(j);
  555. end;
  556. { writing extra zeroes if r < 0 }
  557. while r < 0 do
  558. begin
  559. s[j]:='0';
  560. Dec(j);
  561. Inc(r);
  562. end;
  563. { writing digits and decimal point }
  564. for i:=r + 1 to tlen do
  565. begin
  566. Dec(point);
  567. if point = 0 then
  568. begin
  569. s[j]:='.';
  570. Dec(j);
  571. end;
  572. s[j]:=buf[i];
  573. Dec(j);
  574. end;
  575. { writing sign }
  576. if sign = 1 then
  577. begin
  578. s[j]:='-';
  579. Dec(j);
  580. end;
  581. { writing spaces }
  582. while j > 0 do
  583. begin
  584. s[j]:=' ';
  585. Dec(j);
  586. end;
  587. end;
  588. {
  589. Array Of Char Str() helpers
  590. }
  591. procedure fpc_chararray_sint(v : valsint;len : SizeInt;out a:array of char);compilerproc;
  592. var
  593. ss : shortstring;
  594. maxlen : SizeInt;
  595. begin
  596. int_str(v,ss);
  597. if length(ss)<len then
  598. ss:=space(len-length(ss))+ss;
  599. if length(ss)<high(a)+1 then
  600. maxlen:=length(ss)
  601. else
  602. maxlen:=high(a)+1;
  603. move(ss[1],pchar(@a)^,maxlen);
  604. end;
  605. procedure fpc_chararray_uint(v : valuint;len : SizeInt;out a : array of char);compilerproc;
  606. var
  607. ss : shortstring;
  608. maxlen : SizeInt;
  609. begin
  610. int_str(v,ss);
  611. if length(ss)<len then
  612. ss:=space(len-length(ss))+ss;
  613. if length(ss)<high(a)+1 then
  614. maxlen:=length(ss)
  615. else
  616. maxlen:=high(a)+1;
  617. move(ss[1],pchar(@a)^,maxlen);
  618. end;
  619. {$ifndef CPU64}
  620. procedure fpc_chararray_qword(v : qword;len : SizeInt;out a : array of char);compilerproc;
  621. var
  622. ss : shortstring;
  623. maxlen : SizeInt;
  624. begin
  625. int_str(v,ss);
  626. if length(ss)<len then
  627. ss:=space(len-length(ss))+ss;
  628. if length(ss)<high(a)+1 then
  629. maxlen:=length(ss)
  630. else
  631. maxlen:=high(a)+1;
  632. move(ss[1],pchar(@a)^,maxlen);
  633. end;
  634. procedure fpc_chararray_int64(v : int64;len : SizeInt;out a : array of char);compilerproc;
  635. var
  636. ss : shortstring;
  637. maxlen : SizeInt;
  638. begin
  639. int_str(v,ss);
  640. if length(ss)<len then
  641. ss:=space(len-length(ss))+ss;
  642. if length(ss)<high(a)+1 then
  643. maxlen:=length(ss)
  644. else
  645. maxlen:=high(a)+1;
  646. move(ss[1],pchar(@a)^,maxlen);
  647. end;
  648. {$endif CPU64}
  649. {$ifndef FPUNONE}
  650. procedure fpc_chararray_Float(d : ValReal;len,fr,rt : SizeInt;out a : array of char);compilerproc;
  651. var
  652. ss : shortstring;
  653. maxlen : SizeInt;
  654. begin
  655. str_real(len,fr,d,treal_type(rt),ss);
  656. if length(ss)<high(a)+1 then
  657. maxlen:=length(ss)
  658. else
  659. maxlen:=high(a)+1;
  660. move(ss[1],pchar(@a)^,maxlen);
  661. end;
  662. {$endif}
  663. {$ifdef FPC_HAS_STR_CURRENCY}
  664. procedure fpc_chararray_Currency(c : Currency;len,fr : SizeInt;out a : array of char);compilerproc;
  665. var
  666. ss : shortstring;
  667. maxlen : SizeInt;
  668. begin
  669. str(c:len:fr,ss);
  670. if length(ss)<high(a)+1 then
  671. maxlen:=length(ss)
  672. else
  673. maxlen:=high(a)+1;
  674. move(ss[1],pchar(@a)^,maxlen);
  675. end;
  676. {$endif FPC_HAS_STR_CURRENCY}
  677. {*****************************************************************************
  678. Val() Functions
  679. *****************************************************************************}
  680. Function InitVal(const s:shortstring;out negativ:boolean;out base:byte):ValSInt;
  681. var
  682. Code : SizeInt;
  683. begin
  684. code:=1;
  685. negativ:=false;
  686. base:=10;
  687. if length(s)=0 then
  688. begin
  689. InitVal:=code;
  690. Exit;
  691. end;
  692. {Skip Spaces and Tab}
  693. while (code<=length(s)) and (s[code] in [' ',#9]) do
  694. inc(code);
  695. {Sign}
  696. case s[code] of
  697. '-' : begin
  698. negativ:=true;
  699. inc(code);
  700. end;
  701. '+' : inc(code);
  702. end;
  703. {Base}
  704. if code<=length(s) then
  705. begin
  706. case s[code] of
  707. '$',
  708. 'X',
  709. 'x' : begin
  710. base:=16;
  711. inc(code);
  712. end;
  713. '%' : begin
  714. base:=2;
  715. inc(code);
  716. end;
  717. '&' : begin
  718. Base:=8;
  719. inc(code);
  720. end;
  721. '0' : begin
  722. if (code < length(s)) and (s[code+1] in ['x', 'X']) then
  723. begin
  724. inc(code, 2);
  725. base := 16;
  726. end;
  727. end;
  728. end;
  729. end;
  730. { strip leading zeros }
  731. while ((code < length(s)) and (s[code] = '0')) do begin
  732. inc(code);
  733. end;
  734. InitVal:=code;
  735. end;
  736. Function fpc_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; compilerproc;
  737. var
  738. temp, prev, maxPrevValue, maxNewValue: ValUInt;
  739. base,u : byte;
  740. negative : boolean;
  741. begin
  742. fpc_Val_SInt_ShortStr := 0;
  743. Temp:=0;
  744. Code:=InitVal(s,negative,base);
  745. if Code>length(s) then
  746. exit;
  747. if (s[Code]=#0) then
  748. begin
  749. if (Code>1) and (s[Code-1]='0') then
  750. Code:=0;
  751. exit;
  752. end;
  753. maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  754. if (base = 10) then
  755. maxNewValue := MaxSIntValue + ord(negative)
  756. else
  757. maxNewValue := MaxUIntValue;
  758. while Code<=Length(s) do
  759. begin
  760. case s[Code] of
  761. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  762. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  763. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  764. #0 : break;
  765. else
  766. u:=16;
  767. end;
  768. Prev := Temp;
  769. Temp := Temp*ValUInt(base);
  770. If (u >= base) or
  771. (ValUInt(maxNewValue-u) < Temp) or
  772. (prev > maxPrevValue) Then
  773. Begin
  774. fpc_Val_SInt_ShortStr := 0;
  775. Exit
  776. End;
  777. Temp:=Temp+u;
  778. inc(code);
  779. end;
  780. code := 0;
  781. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  782. If Negative Then
  783. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  784. If Not(Negative) and (base <> 10) Then
  785. {sign extend the result to allow proper range checking}
  786. Case DestSize of
  787. 1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
  788. 2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
  789. {$ifdef cpu64}
  790. 4: fpc_Val_SInt_ShortStr := longint(fpc_Val_SInt_ShortStr);
  791. {$endif cpu64}
  792. End;
  793. end;
  794. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  795. { we have to pass the DestSize parameter on (JM) }
  796. Function int_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  797. Function fpc_Val_UInt_Shortstr(Const S: ShortString; out Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; compilerproc;
  798. var
  799. prev : ValUInt;
  800. base,u : byte;
  801. negative : boolean;
  802. begin
  803. fpc_Val_UInt_Shortstr:=0;
  804. Code:=InitVal(s,negative,base);
  805. If Negative or (Code>length(s)) Then
  806. Exit;
  807. if (s[Code]=#0) then
  808. begin
  809. if (Code>1) and (s[Code-1]='0') then
  810. Code:=0;
  811. exit;
  812. end;
  813. while Code<=Length(s) do
  814. begin
  815. case s[Code] of
  816. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  817. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  818. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  819. #0 : break;
  820. else
  821. u:=16;
  822. end;
  823. prev := fpc_Val_UInt_Shortstr;
  824. If (u>=base) or
  825. (ValUInt(MaxUIntValue-u) div ValUInt(Base)<prev) then
  826. begin
  827. fpc_Val_UInt_Shortstr:=0;
  828. exit;
  829. end;
  830. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
  831. inc(code);
  832. end;
  833. code := 0;
  834. end;
  835. {$ifndef CPU64}
  836. Function fpc_val_int64_shortstr(Const S: ShortString; out Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR']; compilerproc;
  837. var u, temp, prev, maxprevvalue, maxnewvalue : qword;
  838. base : byte;
  839. negative : boolean;
  840. const maxint64=qword($7fffffffffffffff);
  841. maxqword=qword($ffffffffffffffff);
  842. begin
  843. fpc_val_int64_shortstr := 0;
  844. Temp:=0;
  845. Code:=InitVal(s,negative,base);
  846. if Code>length(s) then
  847. exit;
  848. if (s[Code]=#0) then
  849. begin
  850. if (Code>1) and (s[Code-1]='0') then
  851. Code:=0;
  852. exit;
  853. end;
  854. maxprevvalue := maxqword div base;
  855. if (base = 10) then
  856. maxnewvalue := maxint64 + ord(negative)
  857. else
  858. maxnewvalue := maxqword;
  859. while Code<=Length(s) do
  860. begin
  861. case s[Code] of
  862. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  863. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  864. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  865. #0 : break;
  866. else
  867. u:=16;
  868. end;
  869. Prev:=Temp;
  870. Temp:=Temp*qword(base);
  871. If (u >= base) or
  872. (qword(maxnewvalue-u) < temp) or
  873. (prev > maxprevvalue) Then
  874. Begin
  875. fpc_val_int64_shortstr := 0;
  876. Exit
  877. End;
  878. Temp:=Temp+u;
  879. inc(code);
  880. end;
  881. code:=0;
  882. fpc_val_int64_shortstr:=int64(Temp);
  883. If Negative Then
  884. fpc_val_int64_shortstr:=-fpc_val_int64_shortstr;
  885. end;
  886. Function fpc_val_qword_shortstr(Const S: ShortString; out Code: ValSInt): QWord; [public, alias:'FPC_VAL_QWORD_SHORTSTR']; compilerproc;
  887. var u, prev: QWord;
  888. base : byte;
  889. negative : boolean;
  890. const maxqword=qword($ffffffffffffffff);
  891. begin
  892. fpc_val_qword_shortstr:=0;
  893. Code:=InitVal(s,negative,base);
  894. If Negative or (Code>length(s)) Then
  895. Exit;
  896. if (s[Code]=#0) then
  897. begin
  898. if (Code>1) and (s[Code-1]='0') then
  899. Code:=0;
  900. exit;
  901. end;
  902. while Code<=Length(s) do
  903. begin
  904. case s[Code] of
  905. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  906. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  907. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  908. #0 : break;
  909. else
  910. u:=16;
  911. end;
  912. prev := fpc_val_qword_shortstr;
  913. If (u>=base) or
  914. ((QWord(maxqword-u) div QWord(base))<prev) then
  915. Begin
  916. fpc_val_qword_shortstr := 0;
  917. Exit
  918. End;
  919. fpc_val_qword_shortstr:=fpc_val_qword_shortstr*QWord(base) + u;
  920. inc(code);
  921. end;
  922. code := 0;
  923. end;
  924. {$endif CPU64}
  925. {$ifndef FPUNONE}
  926. const
  927. {$ifdef FPC_HAS_TYPE_EXTENDED}
  928. valmaxexpnorm=4932;
  929. {$else}
  930. {$ifdef FPC_HAS_TYPE_DOUBLE}
  931. valmaxexpnorm=308;
  932. {$else}
  933. {$ifdef FPC_HAS_TYPE_SINGLE}
  934. valmaxexpnorm=38;
  935. {$else}
  936. {$error Unknown floating point precision }
  937. {$endif}
  938. {$endif}
  939. {$endif}
  940. {$endif}
  941. {$ifndef FPUNONE}
  942. Function fpc_Val_Real_ShortStr(const s : shortstring; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; compilerproc;
  943. var
  944. hd,
  945. esign,sign : valreal;
  946. exponent,
  947. decpoint,i : SizeInt;
  948. flags : byte;
  949. begin
  950. fpc_Val_Real_ShortStr:=0.0;
  951. code:=1;
  952. exponent:=0;
  953. decpoint:=0;
  954. esign:=1;
  955. flags:=0;
  956. sign:=1;
  957. while (code<=length(s)) and (s[code] in [' ',#9]) do
  958. inc(code);
  959. if code<=length(s) then
  960. case s[code] of
  961. '+' : inc(code);
  962. '-' : begin
  963. sign:=-1;
  964. inc(code);
  965. end;
  966. end;
  967. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  968. begin
  969. { Read integer part }
  970. flags:=flags or 1;
  971. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  972. inc(code);
  973. end;
  974. { Decimal ? }
  975. if (length(s)>=code) and (s[code]='.') then
  976. begin
  977. inc(code);
  978. while (length(s)>=code) and (s[code] in ['0'..'9']) do
  979. begin
  980. { Read fractional part. }
  981. flags:=flags or 2;
  982. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  983. inc(decpoint);
  984. inc(code);
  985. end;
  986. end;
  987. { Again, read integer and fractional part}
  988. if flags=0 then
  989. begin
  990. fpc_Val_Real_ShortStr:=0.0;
  991. exit;
  992. end;
  993. { Exponent ? }
  994. if (length(s)>=code) and (s[code] in ['e','E']) then
  995. begin
  996. inc(code);
  997. if Length(s) >= code then
  998. if s[code]='+' then
  999. inc(code)
  1000. else
  1001. if s[code]='-' then
  1002. begin
  1003. esign:=-1;
  1004. inc(code);
  1005. end;
  1006. if (length(s)<code) or not(s[code] in ['0'..'9']) then
  1007. begin
  1008. fpc_Val_Real_ShortStr:=0.0;
  1009. exit;
  1010. end;
  1011. while (length(s)>=code) and (s[code] in ['0'..'9']) do
  1012. begin
  1013. exponent:=exponent*10;
  1014. exponent:=exponent+ord(s[code])-ord('0');
  1015. inc(code);
  1016. end;
  1017. end;
  1018. { adjust exponent based on decimal point }
  1019. if esign>0 then
  1020. begin
  1021. dec(exponent,decpoint);
  1022. if (exponent<0) then
  1023. begin
  1024. esign:=-1;
  1025. exponent:=-exponent;
  1026. end
  1027. end
  1028. else
  1029. inc(exponent,decpoint);
  1030. { evaluate sign }
  1031. { (before exponent, because the exponent may turn it into a denormal) }
  1032. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*sign;
  1033. { Calculate Exponent }
  1034. hd:=1.0;
  1035. { the magnitude range maximum (normal) is lower in absolute value than the }
  1036. { the magnitude range minimum (denormal). E.g. an extended value can go }
  1037. { up to 1E4932, but "down" to 1E-4951. So make sure that we don't try to }
  1038. { calculate 1E4951 as factor, since that would overflow and result in 0. }
  1039. if (exponent>valmaxexpnorm-2) then
  1040. begin
  1041. for i:=1 to valmaxexpnorm-2 do
  1042. hd:=hd*10.0;
  1043. if esign>0 then
  1044. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  1045. else
  1046. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  1047. dec(exponent,valmaxexpnorm-2);
  1048. hd:=1.0;
  1049. end;
  1050. for i:=1 to exponent do
  1051. hd:=hd*10.0;
  1052. if esign>0 then
  1053. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  1054. else
  1055. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  1056. { Not all characters are read ? }
  1057. if length(s)>=code then
  1058. begin
  1059. fpc_Val_Real_ShortStr:=0.0;
  1060. exit;
  1061. end;
  1062. { success ! }
  1063. code:=0;
  1064. end;
  1065. {$endif}
  1066. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint; [public, alias:'FPC_VAL_ENUM_SHORTSTR']; compilerproc;
  1067. function string_compare(const s1,s2:shortstring):sizeint;
  1068. {We cannot use the > and < operators to compare a string here, because we if the string is
  1069. not found in the enum, we need to return the position of error in "code". Code equals the
  1070. highest matching character of all string compares, which is only known inside the string
  1071. comparison.}
  1072. var i,l:byte;
  1073. c1,c2:char;
  1074. begin
  1075. l:=length(s1);
  1076. if length(s1)>length(s2) then
  1077. l:=length(s2);
  1078. i:=1;
  1079. while i<=l do
  1080. begin
  1081. c1:=s1[i];
  1082. c2:=s2[i];
  1083. if c1<>c2 then
  1084. break;
  1085. inc(i);
  1086. end;
  1087. if i>code then
  1088. code:=i;
  1089. if i<=l then
  1090. string_compare:=byte(c1)-byte(c2)
  1091. else
  1092. string_compare:=length(s1)-length(s2);
  1093. end;
  1094. type Tsorted_array={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1095. o:longint;
  1096. s:Pstring;
  1097. end;
  1098. var l,h,m:cardinal;
  1099. c:sizeint;
  1100. sorted_array:^Tsorted_array;
  1101. spaces:byte;
  1102. t:shortstring;
  1103. label error;
  1104. begin
  1105. {Val for numbers accepts spaces at the start, so lets do the same
  1106. for enums. Skip spaces at the start of the string.}
  1107. spaces:=1;
  1108. code:=1;
  1109. while (spaces<=length(s)) and (s[spaces]=' ') do
  1110. inc(spaces);
  1111. t:=upcase(copy(s,spaces,255));
  1112. sorted_array:=pointer(Pcardinal(str2ordindex)+1);
  1113. {Use a binary search to get the string.}
  1114. l:=1;
  1115. h:=Pcardinal(str2ordindex)^;
  1116. repeat
  1117. m:=(l+h) div 2;
  1118. c:=string_compare(t,upcase(sorted_array[m-1].s^));
  1119. if c>0 then
  1120. l:=m+1
  1121. else if c<0 then
  1122. h:=m-1
  1123. else
  1124. break;
  1125. if l>h then
  1126. begin
  1127. {Not found...}
  1128. inc(code,spaces-1); {Add skipped spaces again.}
  1129. {The result of val in case of error is undefined, don't assign a function result.}
  1130. exit;
  1131. end;
  1132. until false;
  1133. code:=0;
  1134. fpc_val_enum_shortstr:=sorted_array[m-1].o;
  1135. end;
  1136. {Redeclare fpc_val_enum_shortstr for internal use in the system unit.}
  1137. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint;external name 'FPC_VAL_ENUM_SHORTSTR';
  1138. function fpc_Val_Currency_ShortStr(const s : shortstring; out Code : ValSInt): currency; [public, alias:'FPC_VAL_CURRENCY_SHORTSTR']; compilerproc;
  1139. const
  1140. MaxInt64 : Int64 = $7FFFFFFFFFFFFFFF;
  1141. Int64Edge : Int64 = ($7FFFFFFFFFFFFFFF - 10) div 10;
  1142. Int64Edge2 : Int64 = $7FFFFFFFFFFFFFFF div 10;
  1143. var
  1144. res : Int64;
  1145. i,j,power,sign,len : longint;
  1146. FracOverflow : boolean;
  1147. begin
  1148. fpc_Val_Currency_ShortStr:=0;
  1149. res:=0;
  1150. len:=Length(s);
  1151. Code:=1;
  1152. sign:=1;
  1153. power:=0;
  1154. while True do
  1155. if Code > len then
  1156. exit
  1157. else
  1158. if s[Code] in [' ', #9] then
  1159. Inc(Code)
  1160. else
  1161. break;
  1162. { Read sign }
  1163. case s[Code] of
  1164. '+' : Inc(Code);
  1165. '-' : begin
  1166. sign:=-1;
  1167. inc(code);
  1168. end;
  1169. end;
  1170. { Read digits }
  1171. FracOverflow:=False;
  1172. i:=0;
  1173. while Code <= len do
  1174. begin
  1175. case s[Code] of
  1176. '0'..'9':
  1177. begin
  1178. j:=Ord(s[code])-Ord('0');
  1179. { check overflow }
  1180. if (res <= Int64Edge) or (res <= (MaxInt64 - j) div 10) then
  1181. begin
  1182. res:=res*10 + j;
  1183. Inc(i);
  1184. end
  1185. else
  1186. if power = 0 then
  1187. { exit if integer part overflow }
  1188. exit
  1189. else
  1190. begin
  1191. if not FracOverflow and (j >= 5) and (res < MaxInt64) then
  1192. { round if first digit of fractional part overflow }
  1193. Inc(res);
  1194. FracOverflow:=True;
  1195. end;
  1196. end;
  1197. '.':
  1198. begin
  1199. if power = 0 then
  1200. begin
  1201. power:=1;
  1202. i:=0;
  1203. end
  1204. else
  1205. exit;
  1206. end;
  1207. else
  1208. break;
  1209. end;
  1210. Inc(Code);
  1211. end;
  1212. if (i = 0) and (power = 0) then
  1213. exit;
  1214. if power <> 0 then
  1215. power:=i;
  1216. power:=4 - power;
  1217. { Exponent? }
  1218. if Code <= len then
  1219. if s[Code] in ['E', 'e'] then
  1220. begin
  1221. Inc(Code);
  1222. if Code > len then
  1223. exit;
  1224. i:=1;
  1225. case s[Code] of
  1226. '+':
  1227. Inc(Code);
  1228. '-':
  1229. begin
  1230. i:=-1;
  1231. Inc(Code);
  1232. end;
  1233. end;
  1234. { read exponent }
  1235. j:=0;
  1236. while Code <= len do
  1237. if s[Code] in ['0'..'9'] then
  1238. begin
  1239. if j > 4951 then
  1240. exit;
  1241. j:=j*10 + (Ord(s[code])-Ord('0'));
  1242. Inc(Code);
  1243. end
  1244. else
  1245. exit;
  1246. power:=power + j*i;
  1247. end
  1248. else
  1249. exit;
  1250. if power > 0 then
  1251. begin
  1252. for i:=1 to power do
  1253. if res <= Int64Edge2 then
  1254. res:=res*10
  1255. else
  1256. exit;
  1257. end
  1258. else
  1259. for i:=1 to -power do
  1260. begin
  1261. if res <= MaxInt64 - 5 then
  1262. Inc(res, 5);
  1263. res:=res div 10;
  1264. end;
  1265. res:=res*sign;
  1266. fpc_Val_Currency_ShortStr:=PCurrency(@res)^;
  1267. Code:=0;
  1268. end;
  1269. Procedure SetString (Out S : Shortstring; Buf : PChar; Len : SizeInt);
  1270. begin
  1271. If Len > High(S) then
  1272. Len := High(S);
  1273. SetLength(S,Len);
  1274. If Buf<>Nil then
  1275. begin
  1276. Move (Buf[0],S[1],Len);
  1277. end;
  1278. end;
  1279. function ShortCompareText(const S1, S2: shortstring): SizeInt;
  1280. var
  1281. c1, c2: Byte;
  1282. i: Integer;
  1283. L1, L2, Count: SizeInt;
  1284. P1, P2: PChar;
  1285. begin
  1286. L1 := Length(S1);
  1287. L2 := Length(S2);
  1288. if L1 > L2 then
  1289. Count := L2
  1290. else
  1291. Count := L1;
  1292. i := 0;
  1293. P1 := @S1[1];
  1294. P2 := @S2[1];
  1295. while i < count do
  1296. begin
  1297. c1 := byte(p1^);
  1298. c2 := byte(p2^);
  1299. if c1 <> c2 then
  1300. begin
  1301. if c1 in [97..122] then
  1302. Dec(c1, 32);
  1303. if c2 in [97..122] then
  1304. Dec(c2, 32);
  1305. if c1 <> c2 then
  1306. Break;
  1307. end;
  1308. Inc(P1); Inc(P2); Inc(I);
  1309. end;
  1310. if i < count then
  1311. ShortCompareText := c1 - c2
  1312. else
  1313. ShortCompareText := L1 - L2;
  1314. end;