2
0

sstrings.inc 47 KB

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