sstrings.inc 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924
  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. {$ifndef FPC_HAS_SHORTSTR_SETLENGTH}
  14. {$define FPC_HAS_SHORTSTR_SETLENGTH}
  15. procedure fpc_Shortstr_SetLength(var s:shortstring;len:SizeInt);[Public,Alias : 'FPC_SHORTSTR_SETLENGTH']; compilerproc;
  16. begin
  17. if Len>255 then
  18. Len:=255;
  19. s[0]:=chr(len);
  20. end;
  21. {$endif FPC_HAS_SHORTSTR_SETLENGTH}
  22. {$ifndef FPC_HAS_SHORTSTR_COPY}
  23. {$define FPC_HAS_SHORTSTR_COPY}
  24. function fpc_shortstr_copy(const s : shortstring;index : SizeInt;count : SizeInt): shortstring;compilerproc;
  25. begin
  26. if count<0 then
  27. count:=0;
  28. if index>1 then
  29. dec(index)
  30. else
  31. index:=0;
  32. if index>length(s) then
  33. count:=0
  34. else
  35. if count>length(s)-index then
  36. count:=length(s)-index;
  37. fpc_shortstr_Copy[0]:=chr(Count);
  38. fpc_shortstr_shortstr_intern_charmove(s,Index+1,fpc_shortstr_Copy,1,Count);
  39. end;
  40. {$endif FPC_HAS_SHORTSTR_COPY}
  41. {$ifndef FPC_HAS_SHORTSTR_DELETE}
  42. {$define FPC_HAS_SHORTSTR_DELETE}
  43. procedure {$ifdef VER3_0}delete{$else}fpc_shortstr_delete{$endif}(var s : shortstring;index : SizeInt;count : SizeInt);
  44. begin
  45. if index<=0 then
  46. exit;
  47. if (Index<=Length(s)) and (Count>0) then
  48. begin
  49. if Count>length(s)-Index then
  50. Count:=length(s)-Index+1;
  51. s[0]:=Chr(length(s)-Count);
  52. if Index<=Length(s) then
  53. fpc_shortstr_shortstr_intern_charmove(s,Index+Count,s,Index,Length(s)-Index+1);
  54. end;
  55. end;
  56. {$endif FPC_HAS_SHORTSTR_DELETE}
  57. {$ifndef FPC_HAS_SHORTSTR_INSERT}
  58. {$define FPC_HAS_SHORTSTR_INSERT}
  59. procedure {$ifdef ver3_0}insert{$else}fpc_shortstr_insert{$endif}(const source : shortstring;var s : shortstring;index : SizeInt);
  60. var
  61. cut,srclen,indexlen : SizeInt;
  62. begin
  63. if index<1 then
  64. index:=1;
  65. if index>length(s) then
  66. begin
  67. index:=length(s)+1;
  68. if index>high(s) then
  69. exit;
  70. end;
  71. indexlen:=Length(s)-Index+1;
  72. srclen:=length(Source);
  73. if sizeInt(length(source))+sizeint(length(s))>=sizeof(s) then
  74. begin
  75. cut:=sizeInt(length(source))+sizeint(length(s))-sizeof(s)+1;
  76. if cut>indexlen then
  77. begin
  78. dec(srclen,cut-indexlen);
  79. indexlen:=0;
  80. end
  81. else
  82. dec(indexlen,cut);
  83. end;
  84. fpc_shortstr_shortstr_intern_charmove(s,Index,s,Index+srclen,indexlen);
  85. fpc_shortstr_shortstr_intern_charmove(Source,1,s,Index,srclen);
  86. s[0]:=chr(index+srclen+indexlen-1);
  87. end;
  88. {$endif FPC_HAS_SHORTSTR_INSERT}
  89. {$ifndef FPC_HAS_SHORTSTR_INSERT_CHAR}
  90. {$define FPC_HAS_SHORTSTR_INSERT_CHAR}
  91. procedure {$ifdef ver3_0}insert{$else}fpc_shortstr_insert_char{$endif}(source : Char;var s : shortstring;index : SizeInt);
  92. var
  93. indexlen : SizeInt;
  94. begin
  95. if index<1 then
  96. index:=1;
  97. if index>length(s) then
  98. begin
  99. index:=length(s)+1;
  100. if index>high(s) then
  101. exit;
  102. end;
  103. indexlen:=Length(s)-Index+1;
  104. if (sizeint(length(s))+1=sizeof(s)) and (indexlen>0) then
  105. dec(indexlen);
  106. fpc_shortstr_shortstr_intern_charmove(s,Index,s,Index+1,indexlen);
  107. s[Index]:=Source;
  108. s[0]:=chr(index+indexlen);
  109. end;
  110. {$endif FPC_HAS_SHORTSTR_INSERT_CHAR}
  111. {$ifndef FPC_HAS_SHORTSTR_POS_SHORTSTR}
  112. {$define FPC_HAS_SHORTSTR_POS_SHORTSTR}
  113. function pos(const substr : shortstring;const s : shortstring; Offset : Sizeint = 1):SizeInt;
  114. var
  115. i,MaxLen : SizeInt;
  116. pc : pchar;
  117. begin
  118. Pos:=0;
  119. if (Length(SubStr)>0) and (Offset>0) and (Offset<=Length(S)) then
  120. begin
  121. MaxLen:=sizeint(Length(s))-Length(SubStr);
  122. i:=Offset-1;
  123. pc:=@s[Offset];
  124. while (i<=MaxLen) do
  125. begin
  126. inc(i);
  127. if (SubStr[1]=pc^) and
  128. (CompareChar(Substr[1],pc^,Length(SubStr))=0) then
  129. begin
  130. Pos:=i;
  131. exit;
  132. end;
  133. inc(pc);
  134. end;
  135. end;
  136. end;
  137. {$endif FPC_HAS_SHORTSTR_POS_SHORTSTR}
  138. {$ifndef FPC_HAS_SHORTSTR_POS_CHAR}
  139. {$define FPC_HAS_SHORTSTR_POS_CHAR}
  140. {Faster when looking for a single char...}
  141. function pos(c:char;const s:shortstring; Offset : Sizeint = 1 ):SizeInt;
  142. var
  143. i : SizeInt;
  144. pc : pchar;
  145. begin
  146. Pos:=0;
  147. if (Offset<1) or (Offset>Length(S)) then
  148. exit;
  149. pc:=@s[Offset];
  150. for i:=Offset to length(s) do
  151. begin
  152. if pc^=c then
  153. begin
  154. pos:=i;
  155. exit;
  156. end;
  157. inc(pc);
  158. end;
  159. pos:=0;
  160. end;
  161. {$endif FPC_HAS_SHORTSTR_POS_CHAR}
  162. function fpc_char_copy(c:char;index : SizeInt;count : SizeInt): shortstring;compilerproc;
  163. begin
  164. if (index=1) and (Count>0) then
  165. fpc_char_Copy:=c
  166. else
  167. fpc_char_Copy:='';
  168. end;
  169. function pos(const substr : shortstring;c:char; Offset : Sizeint = 1): SizeInt;
  170. begin
  171. if (length(substr)=1) and (substr[1]=c) and (Offset=1) then
  172. Pos:=1
  173. else
  174. Pos:=0;
  175. end;
  176. {$if not defined(FPC_UPCASE_CHAR) or not defined(FPC_LOWERCASE_CHAR)}
  177. {$ifdef IBM_CHAR_SET}
  178. const
  179. UpCaseTbl : shortstring[7]=#154#142#153#144#128#143#165;
  180. LoCaseTbl : shortstring[7]=#129#132#148#130#135#134#164;
  181. {$endif}
  182. {$endif}
  183. {$ifndef FPC_UPCASE_CHAR}
  184. {$define FPC_UPCASE_CHAR}
  185. function upcase(c : char) : char;
  186. {$IFDEF IBM_CHAR_SET}
  187. var
  188. i : ObjpasInt;
  189. {$ENDIF}
  190. begin
  191. if (c in ['a'..'z']) then
  192. upcase:=char(byte(c)-32)
  193. else
  194. {$IFDEF IBM_CHAR_SET}
  195. begin
  196. i:=Pos(c,LoCaseTbl);
  197. if i>0 then
  198. upcase:=UpCaseTbl[i]
  199. else
  200. upcase:=c;
  201. end;
  202. {$ELSE}
  203. upcase:=c;
  204. {$ENDIF}
  205. end;
  206. {$endif FPC_UPCASE_CHAR}
  207. {$ifndef FPC_UPCASE_SHORTSTR}
  208. {$define FPC_UPCASE_SHORTSTR}
  209. function upcase(const s : shortstring) : shortstring;
  210. var
  211. i : ObjpasInt;
  212. begin
  213. upcase[0]:=s[0];
  214. for i := 1 to length (s) do
  215. upcase[i] := upcase (s[i]);
  216. end;
  217. {$endif FPC_UPCASE_SHORTSTR}
  218. {$ifndef FPC_LOWERCASE_CHAR}
  219. {$define FPC_LOWERCASE_CHAR}
  220. function lowercase(c : char) : char;overload;
  221. {$IFDEF IBM_CHAR_SET}
  222. var
  223. i : ObjpasInt;
  224. {$ENDIF}
  225. begin
  226. if (c in ['A'..'Z']) then
  227. lowercase:=char(byte(c)+32)
  228. else
  229. {$IFDEF IBM_CHAR_SET}
  230. begin
  231. i:=Pos(c,UpCaseTbl);
  232. if i>0 then
  233. lowercase:=LoCaseTbl[i]
  234. else
  235. lowercase:=c;
  236. end;
  237. {$ELSE}
  238. lowercase:=c;
  239. {$ENDIF}
  240. end;
  241. {$endif FPC_LOWERCASE_CHAR}
  242. {$ifndef FPC_LOWERCASE_SHORTSTR}
  243. {$define FPC_LOWERCASE_SHORTSTR}
  244. function lowercase(const s : shortstring) : shortstring; overload;
  245. var
  246. i : ObjpasInt;
  247. begin
  248. lowercase [0]:=s[0];
  249. for i:=1 to length(s) do
  250. lowercase[i]:=lowercase (s[i]);
  251. end;
  252. {$endif FPC_LOWERCASE_SHORTSTR}
  253. const
  254. HexTbl : array[0..15] of char='0123456789ABCDEF';
  255. function hexstr(val : longint;cnt : byte) : shortstring;
  256. var
  257. i : ObjpasInt;
  258. begin
  259. hexstr[0]:=char(cnt);
  260. for i:=cnt downto 1 do
  261. begin
  262. hexstr[i]:=hextbl[val and $f];
  263. val:=val shr 4;
  264. end;
  265. end;
  266. function octstr(val : longint;cnt : byte) : shortstring;
  267. var
  268. i : ObjpasInt;
  269. begin
  270. octstr[0]:=char(cnt);
  271. for i:=cnt downto 1 do
  272. begin
  273. octstr[i]:=hextbl[val and 7];
  274. val:=val shr 3;
  275. end;
  276. end;
  277. function binstr(val : longint;cnt : byte) : shortstring;
  278. var
  279. i : ObjpasInt;
  280. begin
  281. binstr[0]:=char(cnt);
  282. for i:=cnt downto 1 do
  283. begin
  284. binstr[i]:=char(48+val and 1);
  285. val:=val shr 1;
  286. end;
  287. end;
  288. function hexstr(val : int64;cnt : byte) : shortstring;
  289. var
  290. i : ObjpasInt;
  291. begin
  292. hexstr[0]:=char(cnt);
  293. for i:=cnt downto 1 do
  294. begin
  295. hexstr[i]:=hextbl[val and $f];
  296. val:=val shr 4;
  297. end;
  298. end;
  299. function octstr(val : int64;cnt : byte) : shortstring;
  300. var
  301. i : ObjpasInt;
  302. begin
  303. octstr[0]:=char(cnt);
  304. for i:=cnt downto 1 do
  305. begin
  306. octstr[i]:=hextbl[val and 7];
  307. val:=val shr 3;
  308. end;
  309. end;
  310. function binstr(val : int64;cnt : byte) : shortstring;
  311. var
  312. i : ObjpasInt;
  313. begin
  314. binstr[0]:=char(cnt);
  315. for i:=cnt downto 1 do
  316. begin
  317. binstr[i]:=char(48+val and 1);
  318. val:=val shr 1;
  319. end;
  320. end;
  321. {$ifndef FPC_HAS_QWORD_HEX_SHORTSTR}
  322. {$define FPC_HAS_QWORD_HEX_SHORTSTR}
  323. Function hexStr(Val:qword;cnt:byte):shortstring;
  324. begin
  325. hexStr:=hexStr(int64(Val),cnt);
  326. end;
  327. {$endif FPC_HAS_QWORD_HEX_SHORTSTR}
  328. {$ifndef FPC_HAS_QWORD_OCT_SHORTSTR}
  329. {$define FPC_HAS_QWORD_OCT_SHORTSTR}
  330. Function OctStr(Val:qword;cnt:byte):shortstring;
  331. begin
  332. OctStr:=OctStr(int64(Val),cnt);
  333. end;
  334. {$endif FPC_HAS_QWORD_OCT_SHORTSTR}
  335. {$ifndef FPC_HAS_QWORD_BIN_SHORTSTR}
  336. {$define FPC_HAS_QWORD_BIN_SHORTSTR}
  337. Function binStr(Val:qword;cnt:byte):shortstring;
  338. begin
  339. binStr:=binStr(int64(Val),cnt);
  340. end;
  341. {$endif FPC_HAS_QWORD_BIN_SHORTSTR}
  342. {$ifndef FPC_HAS_HEXSTR_POINTER_SHORTSTR}
  343. {$define FPC_HAS_HEXSTR_POINTER_SHORTSTR}
  344. function hexstr(val : pointer) : shortstring;
  345. var
  346. i : ObjpasInt;
  347. v : ptruint;
  348. begin
  349. v:=ptruint(val);
  350. hexstr[0]:=chr(sizeof(pointer)*2);
  351. for i:=sizeof(pointer)*2 downto 1 do
  352. begin
  353. hexstr[i]:=hextbl[v and $f];
  354. v:=v shr 4;
  355. end;
  356. end;
  357. {$endif FPC_HAS_HEXSTR_POINTER_SHORTSTR}
  358. {$ifndef FPC_HAS_SPACE_SHORTSTR}
  359. {$define FPC_HAS_SPACE_SHORTSTR}
  360. function space (b : byte): shortstring;
  361. begin
  362. space[0] := chr(b);
  363. FillChar (Space[1],b,' ');
  364. end;
  365. {$endif FPC_HAS_SPACE_SHORTSTR}
  366. {*****************************************************************************
  367. Str() Helpers
  368. *****************************************************************************}
  369. procedure fpc_shortstr_SInt(v : valSInt;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_SINT']; compilerproc;
  370. begin
  371. int_str(v,s);
  372. if length(s)<len then
  373. s:=space(len-length(s))+s;
  374. end;
  375. procedure fpc_shortstr_UInt(v : valUInt;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_UINT']; compilerproc;
  376. begin
  377. int_str_unsigned(v,s);
  378. if length(s)<len then
  379. s:=space(len-length(s))+s;
  380. end;
  381. {$ifndef CPU64}
  382. procedure fpc_shortstr_qword(v : qword;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_QWORD']; compilerproc;
  383. begin
  384. int_str_unsigned(v,s);
  385. if length(s)<len then
  386. s:=space(len-length(s))+s;
  387. end;
  388. procedure fpc_shortstr_int64(v : int64;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_INT64']; compilerproc;
  389. begin
  390. int_str(v,s);
  391. if length(s)<len then
  392. s:=space(len-length(s))+s;
  393. end;
  394. {$endif CPU64}
  395. {$if defined(CPU16) or defined(CPU8)}
  396. procedure fpc_shortstr_longword(v : longword;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_LONGWORD']; compilerproc;
  397. begin
  398. int_str_unsigned(v,s);
  399. if length(s)<len then
  400. s:=space(len-length(s))+s;
  401. end;
  402. procedure fpc_shortstr_longint(v : longint;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_LONGINT']; compilerproc;
  403. begin
  404. int_str(v,s);
  405. if length(s)<len then
  406. s:=space(len-length(s))+s;
  407. end;
  408. procedure fpc_shortstr_word(v : word;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_WORD']; compilerproc;
  409. begin
  410. int_str_unsigned(v,s);
  411. if length(s)<len then
  412. s:=space(len-length(s))+s;
  413. end;
  414. procedure fpc_shortstr_smallint(v : smallint;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_SMALLINT']; compilerproc;
  415. begin
  416. int_str(v,s);
  417. if length(s)<len then
  418. s:=space(len-length(s))+s;
  419. end;
  420. {$endif CPU16 or CPU8}
  421. { fpc_shortstr_sInt must appear before this file is included, because }
  422. { it's used inside real2str.inc and otherwise the searching via the }
  423. { compilerproc name will fail (JM) }
  424. {$ifndef FPUNONE}
  425. {$I flt_conv.inc}
  426. {$endif}
  427. {$ifndef FPUNONE}
  428. procedure fpc_shortstr_float(d : ValReal;len,fr,rt : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT']; compilerproc;
  429. begin
  430. str_real(len,fr,d,treal_type(rt),s);
  431. end;
  432. {$endif}
  433. {$ifndef FPC_STR_ENUM_INTERN}
  434. function fpc_shortstr_enum_intern(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring): longint;
  435. {$ifndef FPC_HAS_FEATURE_RTTI}
  436. begin
  437. int_str(ordinal,s);
  438. if length(s)<len then
  439. s:=space(len-length(s))+s;
  440. end;
  441. {$else with RTTI feature}
  442. { The following contains the TTypeInfo/TTypeData records from typinfo.pp
  443. specialized for the tkEnumeration case (and stripped of unused things). }
  444. type
  445. PPstring=^Pstring;
  446. Penum_typeinfo=^Tenum_typeinfo;
  447. Tenum_typeinfo={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  448. kind:TTypeKind; { always tkEnumeration }
  449. num_chars:byte;
  450. chars:array[0..0] of char; { variable length with size of num_chars }
  451. end;
  452. {$push}
  453. {$packrecords c}
  454. Penum_typedata=^Tenum_typedata;
  455. Tenum_typedata={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  456. {$if declared(TRttiDataCommon)}
  457. Common: TRttiDataCommon;
  458. {$endif}
  459. case TTypeKind of
  460. {$ifndef VER3_0}
  461. tkInt64,tkQWord,
  462. {$endif VER3_0}
  463. tkInteger,tkChar,tkEnumeration,tkBool,tkWChar: (
  464. OrdType : Byte;
  465. case TTypeKind of
  466. tkInteger,tkChar,tkEnumeration,tkBool,tkWChar: (
  467. MinValue,MaxValue : Longint;
  468. case TTypeKind of
  469. tkEnumeration: (
  470. BaseTypeRef : pointer
  471. );
  472. {$ifndef VER3_0}
  473. {tkBool with OrdType=otSQWord }
  474. tkInt64:
  475. (MinInt64Value, MaxInt64Value: Int64);
  476. {tkBool with OrdType=otUQWord }
  477. tkQWord:
  478. (MinQWordValue, MaxQWordValue: QWord);
  479. {$endif VER3_0}
  480. );
  481. );
  482. { more data here, but not needed }
  483. end;
  484. { Pascal data types for the ordinal enum value to string table. It consists of a header
  485. that indicates what type of data the table stores, either a direct lookup table (when
  486. o = lookup) or a set of ordered (ordinal value, string) tuples (when o = search). }
  487. { A single entry in the set of ordered tuples }
  488. Psearch_data=^Tsearch_data;
  489. Tsearch_data={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  490. value:longint;
  491. name:Pstring;
  492. end;
  493. Penum_ord_to_string=^Tenum_ord_to_string;
  494. Tenum_ord_to_string={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  495. o:(lookup,search);
  496. case integer of
  497. 0: (lookup_data:array[0..0] of Pstring);
  498. 1: (num_entries:longint;
  499. search_data:array[0..0] of Tsearch_data);
  500. end;
  501. {$pop}
  502. var
  503. enum_o2s : Penum_ord_to_string;
  504. header:Penum_typeinfo;
  505. body:Penum_typedata;
  506. res:Pshortstring;
  507. sorted_data:Psearch_data;
  508. spaces,i,m,h,l:longint;
  509. begin
  510. { set default return value }
  511. fpc_shortstr_enum_intern:=107;
  512. enum_o2s:=Penum_ord_to_string(ord2strindex);
  513. { depending on the type of table in ord2strindex retrieve the data }
  514. if (enum_o2s^.o=lookup) then
  515. begin
  516. { direct lookup table }
  517. header:=Penum_typeinfo(typinfo);
  518. { calculate address of enum rtti body: add the actual size of the
  519. enum_rtti_header, and then align. Use an alignment of 1 (which
  520. does nothing) in case FPC_REQUIRES_PROPER_ALIGNMENT is not set
  521. to avoid the need for an if in this situation }
  522. {$ifdef VER3_0}
  523. body:=Penum_typedata(aligntoptr(pointer(header) + 2 * sizeof(byte) { kind, num_chars } + header^.num_chars));
  524. {$else VER3_0}
  525. body:=Penum_typedata(aligntoqword(pointer(header) + 2 * sizeof(byte) { kind, num_chars } + header^.num_chars));
  526. {$endif VER3_0}
  527. with body^ do
  528. begin
  529. { Bounds check for the ordinal value for this enum }
  530. if (ordinal<minvalue) or (ordinal>maxvalue) then
  531. exit;
  532. { make the ordinal index for lookup zero-based }
  533. dec(ordinal,minvalue);
  534. end;
  535. { temporarily disable range checking because of the access to the array[0..0]
  536. member of Tenum_ord_to_string_lookup }
  537. {$push}{$R-}
  538. res:=enum_o2s^.lookup_data[ordinal];
  539. {$pop}
  540. if (not assigned(res)) then
  541. exit;
  542. s:=res^;
  543. end
  544. else
  545. begin
  546. { The compiler did generate a sorted array of (ordvalue,Pstring) tuples }
  547. sorted_data:=@enum_o2s^.search_data;
  548. { Use a binary search to get the string }
  549. l:=0;
  550. { temporarily disable range checking because of the access to the array[0..0]
  551. member of Tenum_ord_to_string_search }
  552. {$push}{$R-}
  553. h:=enum_o2s^.num_entries-1;
  554. repeat
  555. m:=(l+h) div 2;
  556. if ordinal>sorted_data[m].value then
  557. l:=m+1
  558. else if ordinal<sorted_data[m].value then
  559. h:=m-1
  560. else
  561. break;
  562. if l>h then
  563. exit; { Ordinal value not found? Exit }
  564. until false;
  565. {$pop}
  566. s:=sorted_data[m].name^;
  567. end;
  568. { Pad the string with spaces if necessary }
  569. if (len>length(s)) then
  570. begin
  571. spaces:=len-length(s);
  572. for i:=1 to spaces do
  573. s[length(s)+i]:=' ';
  574. inc(byte(s[0]),spaces);
  575. end;
  576. fpc_shortstr_enum_intern:=0;
  577. end;
  578. {$endif with RTTI feature}
  579. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);[public,alias:'FPC_SHORTSTR_ENUM'];compilerproc;
  580. var
  581. res: longint;
  582. begin
  583. res:=fpc_shortstr_enum_intern(ordinal,len,typinfo,ord2strindex,s);
  584. if (res<>0) then
  585. runerror(107);
  586. end;
  587. { also define alias for internal use in the system unit }
  588. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);external name 'FPC_SHORTSTR_ENUM';
  589. {$endif FPC_SHORTSTR_ENUM_INTERN}
  590. procedure fpc_shortstr_bool(b : boolean;len:sizeint;out s:shortstring);[public,alias:'FPC_SHORTSTR_BOOL'];compilerproc;
  591. begin
  592. if b then
  593. s:='TRUE'
  594. else
  595. s:='FALSE';
  596. if length(s)<len then
  597. s:=space(len-length(s))+s;
  598. end;
  599. { also define alias for internal use in the system unit }
  600. procedure fpc_shortstr_bool(b : boolean;len:sizeint;out s:shortstring);external {$ifndef cpujvm}name 'FPC_SHORTSTR_BOOL'{$endif};
  601. procedure fpc_shortstr_currency({$ifdef cpujvm}constref{$endif} c : currency; len,f : SizeInt; out s : shortstring);[public,alias:'FPC_SHORTSTR_CURRENCY']; compilerproc;
  602. const
  603. MinLen = 8; { Minimal string length in scientific format }
  604. var
  605. buf : array[1..19] of char;
  606. i,j,k,reslen,tlen,sign,r,point : ObjpasInt;
  607. ic : qword;
  608. begin
  609. fillchar(buf,length(buf),'0');
  610. { default value for length is -32767 }
  611. if len=-32767 then
  612. len:=25;
  613. if PInt64(@c)^ >= 0 then
  614. begin
  615. ic:=QWord(PInt64(@c)^);
  616. sign:=0;
  617. end
  618. else
  619. begin
  620. sign:=1;
  621. ic:=QWord(-PInt64(@c)^);
  622. end;
  623. { converting to integer string }
  624. tlen:=0;
  625. repeat
  626. Inc(tlen);
  627. buf[tlen]:=Chr(ic mod 10 + $30);
  628. ic:=ic div 10;
  629. until ic = 0;
  630. { calculating:
  631. reslen - length of result string,
  632. r - rounding or appending zeroes,
  633. point - place of decimal point }
  634. reslen:=tlen;
  635. if f <> 0 then
  636. Inc(reslen); { adding decimal point length }
  637. if f < 0 then
  638. begin
  639. { scientific format }
  640. Inc(reslen,5); { adding length of sign and exponent }
  641. if len < MinLen then
  642. len:=MinLen;
  643. r:=reslen-len;
  644. if reslen < len then
  645. reslen:=len;
  646. if r > 0 then
  647. begin
  648. reslen:=len;
  649. point:=tlen - r;
  650. end
  651. else
  652. point:=tlen;
  653. end
  654. else
  655. begin
  656. { fixed format }
  657. Inc(reslen, sign);
  658. { prepending fractional part with zeroes }
  659. while tlen < 5 do
  660. begin
  661. Inc(reslen);
  662. Inc(tlen);
  663. buf[tlen]:='0';
  664. end;
  665. { Currency have 4 digits in fractional part }
  666. r:=4 - f;
  667. point:=f;
  668. if point <> 0 then
  669. begin
  670. if point > 4 then
  671. point:=4;
  672. Inc(point);
  673. end;
  674. Dec(reslen,r);
  675. end;
  676. { rounding string if r > 0 }
  677. if r > 0 then
  678. begin
  679. k := 0;
  680. i := r+2;
  681. if i > tlen then
  682. i := tlen+1;
  683. if buf[i-2] >= '5' then
  684. begin
  685. if buf[i-1] < '9' then
  686. buf[i-1] := chr(ord(buf[i-1])+1)
  687. else
  688. begin
  689. buf[i-1] := '0';
  690. k := 1;
  691. end;
  692. end;
  693. If (k=1) and (buf[i-1]='0') then
  694. begin
  695. { 1.9996 rounded to two decimal digits after the decimal separator must result in
  696. 2.00, i.e. the rounding is propagated
  697. }
  698. while buf[i]='9' do
  699. begin
  700. buf[i]:='0';
  701. inc(i);
  702. end;
  703. buf[i]:=chr(Ord(buf[i])+1);
  704. { did we add another digit? This happens when rounding
  705. e.g. 99.9996 to two decimal digits after the decimal separator which should result in
  706. 100.00
  707. }
  708. if i>tlen then
  709. begin
  710. inc(reslen);
  711. inc(tlen);
  712. end;
  713. end;
  714. end;
  715. { preparing result string }
  716. if reslen<len then
  717. reslen:=len;
  718. if reslen>High(s) then
  719. begin
  720. if r < 0 then
  721. Inc(r, reslen - High(s));
  722. reslen:=High(s);
  723. end;
  724. SetLength(s,reslen);
  725. j:=reslen;
  726. if f<0 then
  727. begin
  728. { writing power of 10 part }
  729. if PInt64(@c)^ = 0 then
  730. k:=0
  731. else
  732. k:=tlen-5;
  733. if k >= 0 then
  734. s[j-2]:='+'
  735. else
  736. begin
  737. s[j-2]:='-';
  738. k:=-k;
  739. end;
  740. s[j]:=Chr(k mod 10 + $30);
  741. Dec(j);
  742. s[j]:=Chr(k div 10 + $30);
  743. Dec(j,2);
  744. s[j]:='E';
  745. Dec(j);
  746. end;
  747. { writing extra zeroes if r < 0 }
  748. while r < 0 do
  749. begin
  750. s[j]:='0';
  751. Dec(j);
  752. Inc(r);
  753. end;
  754. { writing digits and decimal point }
  755. for i:=r + 1 to tlen do
  756. begin
  757. Dec(point);
  758. if point = 0 then
  759. begin
  760. s[j]:='.';
  761. Dec(j);
  762. end;
  763. s[j]:=buf[i];
  764. Dec(j);
  765. end;
  766. { writing sign }
  767. if sign = 1 then
  768. begin
  769. s[j]:='-';
  770. Dec(j);
  771. end;
  772. { writing spaces }
  773. while j > 0 do
  774. begin
  775. s[j]:=' ';
  776. Dec(j);
  777. end;
  778. end;
  779. {
  780. Array Of Char Str() helpers
  781. }
  782. procedure fpc_chararray_sint(v : valsint;len : SizeInt;out a:array of char);compilerproc;
  783. var
  784. ss : shortstring;
  785. maxlen : SizeInt;
  786. begin
  787. int_str(v,ss);
  788. if length(ss)<len then
  789. ss:=space(len-length(ss))+ss;
  790. if length(ss)<high(a)+1 then
  791. maxlen:=length(ss)
  792. else
  793. maxlen:=high(a)+1;
  794. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  795. end;
  796. procedure fpc_chararray_uint(v : valuint;len : SizeInt;out a : array of char);compilerproc;
  797. var
  798. ss : shortstring;
  799. maxlen : SizeInt;
  800. begin
  801. int_str_unsigned(v,ss);
  802. if length(ss)<len then
  803. ss:=space(len-length(ss))+ss;
  804. if length(ss)<high(a)+1 then
  805. maxlen:=length(ss)
  806. else
  807. maxlen:=high(a)+1;
  808. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  809. end;
  810. {$ifndef CPU64}
  811. procedure fpc_chararray_qword(v : qword;len : SizeInt;out a : array of char);compilerproc;
  812. {$ifdef EXCLUDE_COMPLEX_PROCS}
  813. begin
  814. runerror(219);
  815. end;
  816. {$else EXCLUDE_COMPLEX_PROCS}
  817. var
  818. ss : shortstring;
  819. maxlen : SizeInt;
  820. begin
  821. int_str_unsigned(v,ss);
  822. if length(ss)<len then
  823. ss:=space(len-length(ss))+ss;
  824. if length(ss)<high(a)+1 then
  825. maxlen:=length(ss)
  826. else
  827. maxlen:=high(a)+1;
  828. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  829. end;
  830. {$endif EXCLUDE_COMPLEX_PROCS}
  831. procedure fpc_chararray_int64(v : int64;len : SizeInt;out a : array of char);compilerproc;
  832. {$ifdef EXCLUDE_COMPLEX_PROCS}
  833. begin
  834. runerror(219);
  835. end;
  836. {$else EXCLUDE_COMPLEX_PROCS}
  837. var
  838. ss : shortstring;
  839. maxlen : SizeInt;
  840. begin
  841. int_str(v,ss);
  842. if length(ss)<len then
  843. ss:=space(len-length(ss))+ss;
  844. if length(ss)<high(a)+1 then
  845. maxlen:=length(ss)
  846. else
  847. maxlen:=high(a)+1;
  848. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  849. end;
  850. {$endif EXCLUDE_COMPLEX_PROCS}
  851. {$endif CPU64}
  852. {$if defined(CPU16) or defined(CPU8)}
  853. procedure fpc_chararray_longword(v : longword;len : SizeInt;out a : array of char);compilerproc;
  854. var
  855. ss : shortstring;
  856. maxlen : SizeInt;
  857. begin
  858. int_str_unsigned(v,ss);
  859. if length(ss)<len then
  860. ss:=space(len-length(ss))+ss;
  861. if length(ss)<high(a)+1 then
  862. maxlen:=length(ss)
  863. else
  864. maxlen:=high(a)+1;
  865. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  866. end;
  867. procedure fpc_chararray_longint(v : longint;len : SizeInt;out a : array of char);compilerproc;
  868. var
  869. ss : shortstring;
  870. maxlen : SizeInt;
  871. begin
  872. int_str(v,ss);
  873. if length(ss)<len then
  874. ss:=space(len-length(ss))+ss;
  875. if length(ss)<high(a)+1 then
  876. maxlen:=length(ss)
  877. else
  878. maxlen:=high(a)+1;
  879. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  880. end;
  881. procedure fpc_chararray_word(v : word;len : SizeInt;out a : array of char);compilerproc;
  882. var
  883. ss : shortstring;
  884. maxlen : SizeInt;
  885. begin
  886. int_str_unsigned(v,ss);
  887. if length(ss)<len then
  888. ss:=space(len-length(ss))+ss;
  889. if length(ss)<high(a)+1 then
  890. maxlen:=length(ss)
  891. else
  892. maxlen:=high(a)+1;
  893. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  894. end;
  895. procedure fpc_chararray_smallint(v : smallint;len : SizeInt;out a : array of char);compilerproc;
  896. var
  897. ss : shortstring;
  898. maxlen : SizeInt;
  899. begin
  900. int_str(v,ss);
  901. if length(ss)<len then
  902. ss:=space(len-length(ss))+ss;
  903. if length(ss)<high(a)+1 then
  904. maxlen:=length(ss)
  905. else
  906. maxlen:=high(a)+1;
  907. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  908. end;
  909. {$endif CPU16 or CPU8}
  910. {$ifndef FPUNONE}
  911. procedure fpc_chararray_Float(d : ValReal;len,fr,rt : SizeInt;out a : array of char);compilerproc;
  912. var
  913. ss : shortstring;
  914. maxlen : SizeInt;
  915. begin
  916. str_real(len,fr,d,treal_type(rt),ss);
  917. if length(ss)<high(a)+1 then
  918. maxlen:=length(ss)
  919. else
  920. maxlen:=high(a)+1;
  921. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  922. end;
  923. {$endif}
  924. {$ifndef FPC_STR_ENUM_INTERN}
  925. { currently, the avr code generator fails on this procedure, so we disable it,
  926. this is not a good solution but fixing compilation of this procedure for
  927. avr is hard, requires significant changes to the register allocator to take
  928. care of different register classes }
  929. procedure fpc_chararray_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out a : array of char);compilerproc;
  930. var
  931. ss : shortstring;
  932. maxlen : SizeInt;
  933. begin
  934. {$ifdef EXCLUDE_COMPLEX_PROCS}
  935. runerror(219);
  936. {$else EXCLUDE_COMPLEX_PROCS}
  937. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  938. if length(ss)<high(a)+1 then
  939. maxlen:=length(ss)
  940. else
  941. maxlen:=high(a)+1;
  942. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  943. {$endif EXCLUDE_COMPLEX_PROCS}
  944. end;
  945. {$endif not FPC_STR_ENUM_INTERN}
  946. procedure fpc_chararray_bool(b : boolean;len:sizeint;out a : array of char);compilerproc;
  947. var
  948. ss : shortstring;
  949. maxlen : SizeInt;
  950. begin
  951. fpc_shortstr_bool(b,len,ss);
  952. if length(ss)<high(a)+1 then
  953. maxlen:=length(ss)
  954. else
  955. maxlen:=high(a)+1;
  956. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  957. end;
  958. {$ifndef FPC_HAS_CHARARRAY_CURRENCY}
  959. {$define FPC_HAS_CHARARRAY_CURRENCY}
  960. procedure fpc_chararray_Currency(c : Currency;len,fr : SizeInt;out a : array of char);compilerproc;
  961. {$ifdef EXCLUDE_COMPLEX_PROCS}
  962. begin
  963. runerror(217);
  964. end;
  965. {$else EXCLUDE_COMPLEX_PROCS}
  966. var
  967. ss : shortstring;
  968. maxlen : SizeInt;
  969. begin
  970. str(c:len:fr,ss);
  971. if length(ss)<high(a)+1 then
  972. maxlen:=length(ss)
  973. else
  974. maxlen:=high(a)+1;
  975. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  976. end;
  977. {$endif EXCLUDE_COMPLEX_PROCS}
  978. {$endif FPC_HAS_CHARARRAY_CURRENCY}
  979. {*****************************************************************************
  980. Val() Functions
  981. *****************************************************************************}
  982. Function InitVal(const s:shortstring;out negativ:boolean;out base:byte):ValSInt;
  983. var
  984. Code : SizeInt;
  985. begin
  986. code:=1;
  987. negativ:=false;
  988. base:=10;
  989. if length(s)=0 then
  990. begin
  991. InitVal:=code;
  992. Exit;
  993. end;
  994. {Skip Spaces and Tab}
  995. while (code<=length(s)) and (s[code] in [' ',#9]) do
  996. inc(code);
  997. {Sign}
  998. case s[code] of
  999. '-' : begin
  1000. negativ:=true;
  1001. inc(code);
  1002. end;
  1003. '+' : inc(code);
  1004. end;
  1005. {Base}
  1006. if code<=length(s) then
  1007. begin
  1008. case s[code] of
  1009. '$',
  1010. 'X',
  1011. 'x' : begin
  1012. base:=16;
  1013. inc(code);
  1014. end;
  1015. '%' : begin
  1016. base:=2;
  1017. inc(code);
  1018. end;
  1019. '&' : begin
  1020. Base:=8;
  1021. inc(code);
  1022. end;
  1023. '0' : begin
  1024. if (code < length(s)) and (s[code+1] in ['x', 'X']) then
  1025. begin
  1026. inc(code, 2);
  1027. base := 16;
  1028. end;
  1029. end;
  1030. end;
  1031. end;
  1032. { strip leading zeros }
  1033. while ((code < length(s)) and (s[code] = '0')) do begin
  1034. inc(code);
  1035. end;
  1036. InitVal:=code;
  1037. end;
  1038. const
  1039. ValValueArray : array['0'..'f'] of byte = (0,1,2,3,4,5,6,7,8,9,$FF,$FF,$FF,$FF,$FF,$FF,$FF,10,11,12,13,14,15,
  1040. $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,
  1041. 10,11,12,13,14,15);
  1042. Function fpc_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; compilerproc;
  1043. var
  1044. temp, prev, maxPrevValue: ValUInt;
  1045. base,u : byte;
  1046. negative: boolean;
  1047. UnsignedUpperLimit: ValUInt;
  1048. begin
  1049. fpc_Val_SInt_ShortStr := 0;
  1050. Temp:=0;
  1051. Code:=InitVal(s,negative,base);
  1052. { avoid error about being uninitialized }
  1053. UnsignedUpperLimit := 0;
  1054. if (base=10) or negative then
  1055. begin //always limit to either Low(DestType) or High(DestType)
  1056. case DestSize of
  1057. 1: UnsignedUpperLimit := ValUInt(High(ShortInt))+Ord(negative);
  1058. 2: UnsignedUpperLimit := ValUInt(High(SmallInt))+Ord(negative);
  1059. 4: UnsignedUpperLimit := ValUInt(High(LongInt))+Ord(negative);
  1060. {$ifdef CPU64}
  1061. 8: UnsignedUpperLimit := ValUInt(High(Int64))+Ord(negative);
  1062. {$endif CPU64}
  1063. end;
  1064. end
  1065. else
  1066. begin //not decimal and not negative
  1067. case DestSize of
  1068. 1: UnsignedUpperLimit := High(Byte);
  1069. 2: UnsignedUpperLimit := High(Word);
  1070. 4: UnsignedUpperLimit := High(DWord);
  1071. {$ifdef CPU64}
  1072. 8: UnsignedUpperLimit := High(UInt64);
  1073. {$endif CPU64}
  1074. end;
  1075. end;
  1076. if Code>length(s) then
  1077. exit;
  1078. if (s[Code]=#0) then
  1079. begin
  1080. if (Code>1) and (s[Code-1]='0') then
  1081. Code:=0;
  1082. exit;
  1083. end;
  1084. maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  1085. while Code<=Length(s) do
  1086. begin
  1087. u:=16;
  1088. case s[code] of
  1089. '0'..'f' : u:=ValValueArray[S[Code]];
  1090. #0 : break;
  1091. else
  1092. ;
  1093. end;
  1094. Prev := Temp;
  1095. Temp := Temp*ValUInt(base);
  1096. If (u >= base) or
  1097. (prev > maxPrevValue)
  1098. or ((Temp)>(UnsignedUpperLimit-u)) Then
  1099. Begin
  1100. fpc_Val_SInt_ShortStr := 0;
  1101. Exit
  1102. End;
  1103. Temp:=Temp+u;
  1104. inc(code);
  1105. end;
  1106. code := 0;
  1107. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  1108. If Negative Then
  1109. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  1110. If Not(Negative) and (base <> 10) Then
  1111. {sign extend the result to allow proper range checking}
  1112. Case DestSize of
  1113. 1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
  1114. 2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
  1115. {$ifdef cpu64}
  1116. 4: fpc_Val_SInt_ShortStr := longint(fpc_Val_SInt_ShortStr);
  1117. {$endif cpu64}
  1118. End;
  1119. end;
  1120. {$ifndef FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1121. {$define FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1122. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  1123. { we have to pass the DestSize parameter on (JM) }
  1124. Function int_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  1125. {$endif FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1126. Function fpc_Val_UInt_Shortstr({$ifndef VER3_2}DestSize: SizeInt;{$endif VER3_2} Const S: ShortString; out Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; compilerproc;
  1127. var
  1128. base,u : byte;
  1129. negative : boolean;
  1130. UpperLimit: ValUInt;
  1131. begin
  1132. fpc_Val_UInt_Shortstr:=0;
  1133. Code:=InitVal(s,negative,base);
  1134. If Negative or (Code>length(s)) Then
  1135. begin
  1136. if Negative then Code:=Pos('-',S);
  1137. Exit;
  1138. end;
  1139. if (s[Code]=#0) then
  1140. begin
  1141. if (Code>1) and (s[Code-1]='0') then
  1142. Code:=0;
  1143. exit;
  1144. end;
  1145. {$ifndef VER3_2}
  1146. case DestSize of
  1147. 1: UpperLimit:=High(Byte);
  1148. 2: UpperLimit:=High(Word);
  1149. 4: UpperLimit:=High(DWord);
  1150. {$ifdef CPU64}
  1151. 8: UpperLimit:=High(QWord);
  1152. {$endif CPU64}
  1153. else
  1154. { avoid error about being uninitialized }
  1155. UpperLimit:=0;
  1156. end;
  1157. {$else VER3_2}
  1158. UpperLimit:=High(ValUInt); //this preserves 3.2 (and earlier) behaviour
  1159. {$ENDIF}
  1160. while Code<=Length(s) do
  1161. begin
  1162. u:=16;
  1163. case s[code] of
  1164. '0'..'f' : u:=ValValueArray[S[Code]];
  1165. #0 : break;
  1166. else
  1167. ;
  1168. end;
  1169. If (u>=base) or
  1170. (ValUInt(UpperLimit-u) div ValUInt(Base)<fpc_val_uint_shortstr) then
  1171. begin
  1172. fpc_Val_UInt_Shortstr:=0;
  1173. exit;
  1174. end;
  1175. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
  1176. inc(code);
  1177. end;
  1178. code := 0;
  1179. {$ifndef VER3_2}
  1180. case DestSize of
  1181. 1: fpc_Val_UInt_Shortstr:=Byte(fpc_Val_UInt_Shortstr);
  1182. 2: fpc_Val_UInt_Shortstr:=Word(fpc_Val_UInt_Shortstr);
  1183. 4: fpc_Val_UInt_Shortstr:=DWord(fpc_Val_UInt_Shortstr);
  1184. //8: no typecast needed for QWord
  1185. end;
  1186. {$ENDIF}
  1187. end;
  1188. {$ifndef CPU64}
  1189. Function fpc_val_int64_shortstr(Const S: ShortString; out Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR']; compilerproc;
  1190. var u : sizeuint;
  1191. temp, prev, maxprevvalue, maxnewvalue : qword;
  1192. base : byte;
  1193. negative : boolean;
  1194. const maxint64=qword($7fffffffffffffff);
  1195. minint64_unsigned=qword($8000000000000000);
  1196. maxqword=qword($ffffffffffffffff);
  1197. begin
  1198. {$ifdef EXCLUDE_COMPLEX_PROCS}
  1199. runerror(219);
  1200. {$else EXCLUDE_COMPLEX_PROCS}
  1201. fpc_val_int64_shortstr := 0;
  1202. Temp:=0;
  1203. Code:=InitVal(s,negative,base);
  1204. if Code>length(s) then
  1205. exit;
  1206. if (s[Code]=#0) then
  1207. begin
  1208. if (Code>1) and (s[Code-1]='0') then
  1209. Code:=0;
  1210. exit;
  1211. end;
  1212. maxprevvalue := maxqword div base;
  1213. if (base = 10) then
  1214. maxnewvalue := maxint64 + ord(negative)
  1215. else
  1216. maxnewvalue := maxqword;
  1217. while Code<=Length(s) do
  1218. begin
  1219. u:=16;
  1220. case s[code] of
  1221. '0'..'f' : u:=ValValueArray[S[Code]];
  1222. #0 : break;
  1223. else
  1224. ;
  1225. end;
  1226. Prev:=Temp;
  1227. Temp:=Temp*qword(base);
  1228. If (u >= base) or
  1229. (qword(maxnewvalue-u) < temp) or
  1230. (prev > maxprevvalue) or
  1231. ((base<>10) and (negative) and ((Temp+u)>minint64_unsigned)) Then
  1232. Begin
  1233. fpc_val_int64_shortstr := 0;
  1234. Exit
  1235. End;
  1236. Temp:=Temp+u;
  1237. inc(code);
  1238. end;
  1239. code:=0;
  1240. fpc_val_int64_shortstr:=int64(Temp);
  1241. If Negative Then
  1242. fpc_val_int64_shortstr:=-fpc_val_int64_shortstr;
  1243. {$endif EXCLUDE_COMPLEX_PROCS}
  1244. end;
  1245. Function fpc_val_qword_shortstr(Const S: ShortString; out Code: ValSInt): QWord; [public, alias:'FPC_VAL_QWORD_SHORTSTR']; compilerproc;
  1246. var u : sizeuint;
  1247. base : byte;
  1248. negative : boolean;
  1249. const maxqword=qword($ffffffffffffffff);
  1250. begin
  1251. fpc_val_qword_shortstr:=0;
  1252. Code:=InitVal(s,negative,base);
  1253. If Negative or (Code>length(s)) Then
  1254. begin
  1255. if Negative then Code:=Pos('-',S);
  1256. Exit;
  1257. end;
  1258. if (s[Code]=#0) then
  1259. begin
  1260. if (Code>1) and (s[Code-1]='0') then
  1261. Code:=0;
  1262. exit;
  1263. end;
  1264. while Code<=Length(s) do
  1265. begin
  1266. u:=16;
  1267. case s[code] of
  1268. '0'..'f' : u:=ValValueArray[S[Code]];
  1269. #0 : break;
  1270. else
  1271. ;
  1272. end;
  1273. If (u>=base) or
  1274. ((QWord(maxqword-u) div QWord(base))<fpc_val_qword_shortstr) then
  1275. Begin
  1276. fpc_val_qword_shortstr := 0;
  1277. Exit
  1278. End;
  1279. fpc_val_qword_shortstr:=fpc_val_qword_shortstr*QWord(base) + u;
  1280. inc(code);
  1281. end;
  1282. code := 0;
  1283. end;
  1284. {$endif CPU64}
  1285. {$if defined(CPU16) or defined(CPU8)}
  1286. Function fpc_val_longint_shortstr(Const S: ShortString; out Code: ValSInt): LongInt; [public, alias:'FPC_VAL_LONGINT_SHORTSTR']; compilerproc;
  1287. var u, temp, prev, maxprevvalue, maxnewvalue : longword;
  1288. base : byte;
  1289. negative : boolean;
  1290. const maxlongint=longword($7fffffff);
  1291. maxlongword=longword($ffffffff);
  1292. begin
  1293. fpc_val_longint_shortstr := 0;
  1294. Temp:=0;
  1295. Code:=InitVal(s,negative,base);
  1296. if Code>length(s) then
  1297. exit;
  1298. if (s[Code]=#0) then
  1299. begin
  1300. if (Code>1) and (s[Code-1]='0') then
  1301. Code:=0;
  1302. exit;
  1303. end;
  1304. maxprevvalue := maxlongword div base;
  1305. if (base = 10) then
  1306. maxnewvalue := maxlongint + ord(negative)
  1307. else
  1308. maxnewvalue := maxlongword;
  1309. while Code<=Length(s) do
  1310. begin
  1311. u:=16;
  1312. case s[code] of
  1313. '0'..'f' : u:=ValValueArray[S[Code]];
  1314. #0 : break;
  1315. else
  1316. ;
  1317. end;
  1318. Prev:=Temp;
  1319. Temp:=Temp*longword(base);
  1320. If (u >= base) or
  1321. (longword(maxnewvalue-u) < temp) or
  1322. (prev > maxprevvalue) Then
  1323. Begin
  1324. fpc_val_longint_shortstr := 0;
  1325. Exit;
  1326. End;
  1327. Temp:=Temp+u;
  1328. inc(code);
  1329. end;
  1330. code:=0;
  1331. fpc_val_longint_shortstr:=longint(Temp);
  1332. If Negative Then
  1333. fpc_val_longint_shortstr:=-fpc_val_longint_shortstr;
  1334. end;
  1335. Function fpc_val_longword_shortstr(Const S: ShortString; out Code: ValSInt): LongWord; [public, alias:'FPC_VAL_LONGWORD_SHORTSTR']; compilerproc;
  1336. var u, prev: LongWord;
  1337. base : byte;
  1338. negative : boolean;
  1339. const UpperLimit=High(longword);
  1340. begin
  1341. fpc_val_longword_shortstr:=0;
  1342. Code:=InitVal(s,negative,base);
  1343. If Negative or (Code>length(s)) Then
  1344. Exit;
  1345. if (s[Code]=#0) then
  1346. begin
  1347. if (Code>1) and (s[Code-1]='0') then
  1348. Code:=0;
  1349. exit;
  1350. end;
  1351. while Code<=Length(s) do
  1352. begin
  1353. u:=16;
  1354. case s[code] of
  1355. '0'..'f' : u:=ValValueArray[S[Code]];
  1356. #0 : break;
  1357. else
  1358. ;
  1359. end;
  1360. If (u>=base) or
  1361. (LongWord(UpperLimit-u) div LongWord(Base)<fpc_val_longword_shortstr) then
  1362. begin
  1363. fpc_val_longword_shortstr:=0;
  1364. exit;
  1365. end;
  1366. fpc_val_longword_shortstr:=fpc_val_longword_shortstr*base + u;
  1367. inc(code);
  1368. end;
  1369. code := 0;
  1370. end;
  1371. Function fpc_val_smallint_shortstr(Const S: ShortString; out Code: ValSInt): SmallInt; [public, alias:'FPC_VAL_SMALLINT_SHORTSTR']; compilerproc;
  1372. var u, temp, prev, maxprevvalue : word;
  1373. base : byte;
  1374. negative : boolean;
  1375. UnsignedUpperLimit: ValUInt;
  1376. begin
  1377. fpc_val_smallint_shortstr := 0;
  1378. Temp:=0;
  1379. Code:=InitVal(s,negative,base);
  1380. if (base=10) or negative then
  1381. UnsignedUpperLimit := Word(High(SmallInt))+Ord(negative)
  1382. else
  1383. UnsignedUpperLimit := High(Word);
  1384. if Code>length(s) then
  1385. exit;
  1386. if (s[Code]=#0) then
  1387. begin
  1388. if (Code>1) and (s[Code-1]='0') then
  1389. Code:=0;
  1390. exit;
  1391. end;
  1392. maxprevvalue := High(Word) div base;
  1393. while Code<=Length(s) do
  1394. begin
  1395. u:=16;
  1396. case s[code] of
  1397. '0'..'f' : u:=ValValueArray[S[Code]];
  1398. #0 : break;
  1399. else
  1400. ;
  1401. end;
  1402. Prev:=Temp;
  1403. Temp:=Temp*longword(base);
  1404. If (u >= base) or
  1405. (prev > maxPrevValue) or
  1406. ((Temp)>(UnsignedUpperLimit-u)) Then
  1407. Begin
  1408. fpc_val_smallint_shortstr := 0;
  1409. Exit
  1410. End;
  1411. Temp:=Temp+u;
  1412. inc(code);
  1413. end;
  1414. code:=0;
  1415. fpc_val_smallint_shortstr:=SmallInt(Temp);
  1416. If Negative Then
  1417. fpc_val_smallint_shortstr:=-fpc_val_smallint_shortstr;
  1418. end;
  1419. Function fpc_val_word_shortstr(Const S: ShortString; out Code: ValSInt): Word; [public, alias:'FPC_VAL_WORD_SHORTSTR']; compilerproc;
  1420. var u, prev: word;
  1421. base : byte;
  1422. negative : boolean;
  1423. const UpperLimit=High(Word); //this preserves 3.2 (and earlier) behaviour
  1424. begin
  1425. fpc_val_word_shortstr:=0;
  1426. Code:=InitVal(s,negative,base);
  1427. If Negative or (Code>length(s)) Then
  1428. begin
  1429. if Negative then Code:=Pos('-',S);
  1430. Exit;
  1431. end;
  1432. if (s[Code]=#0) then
  1433. begin
  1434. if (Code>1) and (s[Code-1]='0') then
  1435. Code:=0;
  1436. exit;
  1437. end;
  1438. while Code<=Length(s) do
  1439. begin
  1440. u:=16;
  1441. case s[code] of
  1442. '0'..'f' : u:=ValValueArray[S[Code]];
  1443. #0 : break;
  1444. else
  1445. ;
  1446. end;
  1447. If (u>=base) or
  1448. (Word(UpperLimit-u) div Word(Base)<fpc_val_word_shortstr) then
  1449. begin
  1450. fpc_val_word_shortstr:=0;
  1451. exit;
  1452. end;
  1453. fpc_val_word_shortstr:=fpc_val_word_shortstr*base + u;
  1454. inc(code);
  1455. end;
  1456. code := 0;
  1457. end;
  1458. {$endif CPU16 or CPU8}
  1459. {$ifndef FPUNONE}
  1460. Function fpc_Val_Real_ShortStr(const s : shortstring; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; compilerproc;
  1461. begin
  1462. fpc_Val_Real_ShortStr := val_real( s, code );
  1463. end;
  1464. {$endif FPUNONE}
  1465. {$ifndef FPC_STR_ENUM_INTERN}
  1466. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint; [public, alias:'FPC_VAL_ENUM_SHORTSTR']; compilerproc;
  1467. function string_compare(const s1,s2:shortstring):sizeint;
  1468. {We cannot use the > and < operators to compare a string here, because we if the string is
  1469. not found in the enum, we need to return the position of error in "code". Code equals the
  1470. highest matching character of all string compares, which is only known inside the string
  1471. comparison.}
  1472. var i,l:byte;
  1473. c1,c2:char;
  1474. begin
  1475. l:=length(s1);
  1476. if length(s1)>length(s2) then
  1477. l:=length(s2);
  1478. i:=1;
  1479. while i<=l do
  1480. begin
  1481. c1:=s1[i];
  1482. c2:=s2[i];
  1483. if c1<>c2 then
  1484. break;
  1485. inc(i);
  1486. end;
  1487. if i>code then
  1488. code:=i;
  1489. if i<=l then
  1490. string_compare:=byte(c1)-byte(c2)
  1491. else
  1492. string_compare:=length(s1)-length(s2);
  1493. end;
  1494. type Psorted_array=^Tsorted_array;
  1495. Tsorted_array={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1496. o:longint;
  1497. s:Pstring;
  1498. end;
  1499. Pstring_to_ord=^Tstring_to_ord;
  1500. Tstring_to_ord={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1501. count:longint;
  1502. data:array[0..0] of Tsorted_array;
  1503. end;
  1504. var l,h,m:cardinal;
  1505. c:sizeint;
  1506. sorted_array:^Tsorted_array;
  1507. spaces:byte;
  1508. t:shortstring;
  1509. begin
  1510. {Val for numbers accepts spaces at the start, so lets do the same
  1511. for enums. Skip spaces at the start of the string.}
  1512. spaces:=1;
  1513. code:=1;
  1514. while (spaces<=length(s)) and (s[spaces]=' ') do
  1515. inc(spaces);
  1516. t:=upcase(copy(s,spaces,255));
  1517. sorted_array:=pointer(@Pstring_to_ord(str2ordindex)^.data);
  1518. {Use a binary search to get the string.}
  1519. l:=1;
  1520. h:=Pstring_to_ord(str2ordindex)^.count;
  1521. repeat
  1522. m:=(l+h) div 2;
  1523. c:=string_compare(t,upcase(sorted_array[m-1].s^));
  1524. if c>0 then
  1525. l:=m+1
  1526. else if c<0 then
  1527. h:=m-1
  1528. else
  1529. break;
  1530. if l>h then
  1531. begin
  1532. {Not found...}
  1533. inc(code,spaces-1); {Add skipped spaces again.}
  1534. {The result of val in case of error is undefined, don't assign a function result.}
  1535. exit;
  1536. end;
  1537. until false;
  1538. code:=0;
  1539. fpc_val_enum_shortstr:=sorted_array[m-1].o;
  1540. end;
  1541. {Redeclare fpc_val_enum_shortstr for internal use in the system unit.}
  1542. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint;external name 'FPC_VAL_ENUM_SHORTSTR';
  1543. {$endif FPC_STR_ENUM_INTERN}
  1544. function fpc_Val_Currency_ShortStr(const s : shortstring; out Code : ValSInt): currency; [public, alias:'FPC_VAL_CURRENCY_SHORTSTR']; compilerproc;
  1545. {$ifdef EXCLUDE_COMPLEX_PROCS}
  1546. begin
  1547. runerror(217);
  1548. end;
  1549. {$else EXCLUDE_COMPLEX_PROCS}
  1550. const
  1551. MinInt64 : Int64 =-$8000000000000000;
  1552. MinInt64Edge : Int64 = (-$8000000000000000 + 10) div 10;
  1553. var
  1554. { to enable taking the address on the JVM target }
  1555. res : array[0..0] of Int64;
  1556. i,j,power,sign,len : longint;
  1557. FracOverflow : boolean;
  1558. begin
  1559. fpc_Val_Currency_ShortStr:=0;
  1560. res[0]:=0;
  1561. len:=Length(s);
  1562. Code:=1;
  1563. sign:=-1;
  1564. power:=0;
  1565. while True do
  1566. if Code > len then
  1567. exit
  1568. else
  1569. if s[Code] in [' ', #9] then
  1570. Inc(Code)
  1571. else
  1572. break;
  1573. { Read sign }
  1574. case s[Code] of
  1575. '+' : begin
  1576. Inc(Code);
  1577. end;
  1578. '-' : begin
  1579. sign:=+1;
  1580. Inc(Code);
  1581. end;
  1582. end;
  1583. { Read digits }
  1584. FracOverflow:=False;
  1585. i:=0;
  1586. while Code <= len do
  1587. begin
  1588. case s[Code] of
  1589. '0'..'9':
  1590. begin
  1591. j:=Ord(s[code])-Ord('0');
  1592. { check overflow }
  1593. if (res[0] >= MinInt64Edge) or (res[0] >= (MinInt64 + j) div 10) then
  1594. begin
  1595. res[0]:=res[0]*10 - j;
  1596. Inc(i);
  1597. end
  1598. else
  1599. if power = 0 then
  1600. { exit if integer part overflow }
  1601. exit
  1602. else
  1603. begin
  1604. if not FracOverflow and (j >= 5) and (res[0] > MinInt64) then
  1605. { round if first digit of fractional part overflow }
  1606. Dec(res[0]);
  1607. FracOverflow:=True;
  1608. end;
  1609. end;
  1610. '.':
  1611. begin
  1612. if power = 0 then
  1613. begin
  1614. power:=1;
  1615. i:=0;
  1616. end
  1617. else
  1618. exit;
  1619. end;
  1620. else
  1621. break;
  1622. end;
  1623. Inc(Code);
  1624. end;
  1625. if (i = 0) and (power = 0) then
  1626. exit;
  1627. if power <> 0 then
  1628. power:=i;
  1629. power:=4 - power;
  1630. { Exponent? }
  1631. if Code <= len then
  1632. if s[Code] in ['E', 'e'] then
  1633. begin
  1634. Inc(Code);
  1635. if Code > len then
  1636. exit;
  1637. i:=1;
  1638. case s[Code] of
  1639. '+':
  1640. Inc(Code);
  1641. '-':
  1642. begin
  1643. i:=-1;
  1644. Inc(Code);
  1645. end;
  1646. end;
  1647. { read exponent }
  1648. j:=0;
  1649. while Code <= len do
  1650. if s[Code] in ['0'..'9'] then
  1651. begin
  1652. if j > 4951 then
  1653. exit;
  1654. j:=j*10 + (Ord(s[code])-Ord('0'));
  1655. Inc(Code);
  1656. end
  1657. else
  1658. exit;
  1659. power:=power + j*i;
  1660. end
  1661. else
  1662. exit;
  1663. if power > 0 then
  1664. begin
  1665. for i:=1 to power do
  1666. if res[0] >= MinInt64 div 10 then
  1667. res[0]:=res[0]*10
  1668. else
  1669. exit;
  1670. end
  1671. else
  1672. for i:=1 to -power do
  1673. begin
  1674. if res[0] >= MinInt64 + 5 then
  1675. Dec(res[0], 5);
  1676. res[0]:=res[0] div 10;
  1677. end;
  1678. if sign <> 1 then
  1679. if res[0] > MinInt64 then
  1680. res[0]:=res[0]*sign
  1681. else
  1682. exit;
  1683. fpc_Val_Currency_ShortStr:=PCurrency(@res[0])^;
  1684. Code:=0;
  1685. end;
  1686. {$endif EXCLUDE_COMPLEX_PROCS}
  1687. {$ifndef FPC_HAS_SETSTRING_SHORTSTR}
  1688. {$define FPC_HAS_SETSTRING_SHORTSTR}
  1689. Procedure {$ifdef FPC_HAS_CPSTRING}fpc_setstring_shortstr{$else}SetString{$endif}(Out S : Shortstring; Buf : PChar; Len : SizeInt); {$ifdef FPC_HAS_CPSTRING} compilerproc; {$endif FPC_HAS_CPSTRING}
  1690. begin
  1691. If Len > High(S) then
  1692. Len := High(S);
  1693. SetLength(S,Len);
  1694. If Buf<>Nil then
  1695. begin
  1696. Move (Buf[0],S[1],Len);
  1697. end;
  1698. end;
  1699. {$endif FPC_HAS_SETSTRING_SHORTSTR}
  1700. {$ifndef FPC_HAS_COMPARETEXT_SHORTSTR}
  1701. {$define FPC_HAS_COMPARETEXT_SHORTSTR}
  1702. function ShortCompareText(const S1, S2: shortstring): SizeInt;
  1703. var
  1704. c1, c2: Byte;
  1705. i: SizeInt;
  1706. L1, L2, Count: SizeInt;
  1707. P1, P2: PChar;
  1708. begin
  1709. L1 := Length(S1);
  1710. L2 := Length(S2);
  1711. if L1 > L2 then
  1712. Count := L2
  1713. else
  1714. Count := L1;
  1715. i := 0;
  1716. P1 := @S1[1];
  1717. P2 := @S2[1];
  1718. while i < count do
  1719. begin
  1720. c1 := byte(p1^);
  1721. c2 := byte(p2^);
  1722. if c1 <> c2 then
  1723. begin
  1724. if c1 in [97..122] then
  1725. Dec(c1, 32);
  1726. if c2 in [97..122] then
  1727. Dec(c2, 32);
  1728. if c1 <> c2 then
  1729. Break;
  1730. end;
  1731. Inc(P1); Inc(P2); Inc(I);
  1732. end;
  1733. if i < count then
  1734. ShortCompareText := c1 - c2
  1735. else
  1736. ShortCompareText := L1 - L2;
  1737. end;
  1738. {$endif FPC_HAS_COMPARETEXT_SHORTSTR}