sstrings.inc 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174
  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 delete(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 insert(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 insert(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. {$ifdef FLOAT_ASCII_FALLBACK}
  426. {$I real2str.inc}
  427. {$else not FLOAT_ASCII_FALLBACK}
  428. {$I flt_conv.inc}
  429. {$endif FLOAT_ASCII_FALLBACK}
  430. {$endif}
  431. {$ifndef FPUNONE}
  432. procedure fpc_shortstr_float(d : ValReal;len,fr,rt : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT']; compilerproc;
  433. begin
  434. str_real(len,fr,d,treal_type(rt),s);
  435. end;
  436. {$endif}
  437. {$ifndef FPC_STR_ENUM_INTERN}
  438. function fpc_shortstr_enum_intern(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring): longint;
  439. { The following contains the TTypeInfo/TTypeData records from typinfo.pp
  440. specialized for the tkEnumeration case (and stripped of unused things). }
  441. type
  442. PPstring=^Pstring;
  443. Penum_typeinfo=^Tenum_typeinfo;
  444. Tenum_typeinfo={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  445. kind:byte; { always tkEnumeration }
  446. num_chars:byte;
  447. chars:array[0..0] of char; { variable length with size of num_chars }
  448. end;
  449. Penum_typedata=^Tenum_typedata;
  450. Tenum_typedata={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  451. ordtype:byte;
  452. { this seemingly extraneous inner record is here for alignment purposes, so
  453. that its data gets aligned properly (if FPC_REQUIRES_PROPER_ALIGNMENT is
  454. set }
  455. inner: {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  456. minvalue,maxvalue:longint;
  457. basetype:pointer; { required for alignment }
  458. end;
  459. { more data here, but not needed }
  460. end;
  461. { Pascal data types for the ordinal enum value to string table. It consists of a header
  462. that indicates what type of data the table stores, either a direct lookup table (when
  463. o = lookup) or a set of ordered (ordinal value, string) tuples (when o = search). }
  464. { A single entry in the set of ordered tuples }
  465. Psearch_data=^Tsearch_data;
  466. Tsearch_data={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  467. value:longint;
  468. name:Pstring;
  469. end;
  470. Penum_ord_to_string=^Tenum_ord_to_string;
  471. Tenum_ord_to_string={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  472. o:(lookup,search);
  473. case integer of
  474. 0: (lookup_data:array[0..0] of Pstring);
  475. 1: (num_entries:longint;
  476. search_data:array[0..0] of Tsearch_data);
  477. end;
  478. var
  479. enum_o2s : Penum_ord_to_string;
  480. header:Penum_typeinfo;
  481. body:Penum_typedata;
  482. res:Pshortstring;
  483. sorted_data:Psearch_data;
  484. spaces,i,m,h,l:longint;
  485. begin
  486. { set default return value }
  487. fpc_shortstr_enum_intern:=107;
  488. enum_o2s:=Penum_ord_to_string(ord2strindex);
  489. { depending on the type of table in ord2strindex retrieve the data }
  490. if (enum_o2s^.o=lookup) then
  491. begin
  492. { direct lookup table }
  493. header:=Penum_typeinfo(typinfo);
  494. { calculate address of enum rtti body: add the actual size of the
  495. enum_rtti_header, and then align. Use an alignment of 1 (which
  496. does nothing) in case FPC_REQUIRES_PROPER_ALIGNMENT is not set
  497. to avoid the need for an if in this situation }
  498. body:=Penum_typedata(align(ptruint(header) + 2 * sizeof(byte) { kind, num_chars } + header^.num_chars,
  499. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT} 1 {$else} sizeof(pointer) {$endif}));
  500. with (body^.inner) do
  501. begin
  502. { Bounds check for the ordinal value for this enum }
  503. if (ordinal<minvalue) or (ordinal>maxvalue) then
  504. exit;
  505. { make the ordinal index for lookup zero-based }
  506. dec(ordinal,minvalue);
  507. end;
  508. { temporarily disable range checking because of the access to the array[0..0]
  509. member of Tenum_ord_to_string_lookup }
  510. {$push}{$R-}
  511. res:=enum_o2s^.lookup_data[ordinal];
  512. {$pop}
  513. if (not assigned(res)) then
  514. exit;
  515. s:=res^;
  516. end
  517. else
  518. begin
  519. { The compiler did generate a sorted array of (ordvalue,Pstring) tuples }
  520. sorted_data:=@enum_o2s^.search_data;
  521. { Use a binary search to get the string }
  522. l:=0;
  523. { temporarily disable range checking because of the access to the array[0..0]
  524. member of Tenum_ord_to_string_search }
  525. {$push}{$R-}
  526. h:=enum_o2s^.num_entries-1;
  527. repeat
  528. m:=(l+h) div 2;
  529. if ordinal>sorted_data[m].value then
  530. l:=m+1
  531. else if ordinal<sorted_data[m].value then
  532. h:=m-1
  533. else
  534. break;
  535. if l>h then
  536. exit; { Ordinal value not found? Exit }
  537. until false;
  538. {$pop}
  539. s:=sorted_data[m].name^;
  540. end;
  541. { Pad the string with spaces if necessary }
  542. if (len>length(s)) then
  543. begin
  544. spaces:=len-length(s);
  545. for i:=1 to spaces do
  546. s[length(s)+i]:=' ';
  547. inc(byte(s[0]),spaces);
  548. end;
  549. fpc_shortstr_enum_intern:=0;
  550. end;
  551. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);[public,alias:'FPC_SHORTSTR_ENUM'];compilerproc;
  552. var
  553. res: longint;
  554. begin
  555. res:=fpc_shortstr_enum_intern(ordinal,len,typinfo,ord2strindex,s);
  556. if (res<>0) then
  557. runerror(107);
  558. end;
  559. { also define alias for internal use in the system unit }
  560. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);external name 'FPC_SHORTSTR_ENUM';
  561. {$endif FPC_SHORTSTR_ENUM_INTERN}
  562. procedure fpc_shortstr_bool(b : boolean;len:sizeint;out s:shortstring);[public,alias:'FPC_SHORTSTR_BOOL'];compilerproc;
  563. begin
  564. if b then
  565. s:='TRUE'
  566. else
  567. s:='FALSE';
  568. if length(s)<len then
  569. s:=space(len-length(s))+s;
  570. end;
  571. { also define alias for internal use in the system unit }
  572. procedure fpc_shortstr_bool(b : boolean;len:sizeint;out s:shortstring);external {$ifndef cpujvm}name 'FPC_SHORTSTR_BOOL'{$endif};
  573. procedure fpc_shortstr_currency({$ifdef cpujvm}constref{$endif} c : currency; len,f : SizeInt; out s : shortstring);[public,alias:'FPC_SHORTSTR_CURRENCY']; compilerproc;
  574. const
  575. MinLen = 8; { Minimal string length in scientific format }
  576. var
  577. buf : array[1..19] of char;
  578. i,j,k,reslen,tlen,sign,r,point : longint;
  579. ic : qword;
  580. begin
  581. fillchar(buf,length(buf),'0');
  582. { default value for length is -32767 }
  583. if len=-32767 then
  584. len:=25;
  585. if PInt64(@c)^ >= 0 then
  586. begin
  587. ic:=QWord(PInt64(@c)^);
  588. sign:=0;
  589. end
  590. else
  591. begin
  592. sign:=1;
  593. ic:=QWord(-PInt64(@c)^);
  594. end;
  595. { converting to integer string }
  596. tlen:=0;
  597. repeat
  598. Inc(tlen);
  599. buf[tlen]:=Chr(ic mod 10 + $30);
  600. ic:=ic div 10;
  601. until ic = 0;
  602. { calculating:
  603. reslen - length of result string,
  604. r - rounding or appending zeroes,
  605. point - place of decimal point }
  606. reslen:=tlen;
  607. if f <> 0 then
  608. Inc(reslen); { adding decimal point length }
  609. if f < 0 then
  610. begin
  611. { scientific format }
  612. Inc(reslen,5); { adding length of sign and exponent }
  613. if len < MinLen then
  614. len:=MinLen;
  615. r:=reslen-len;
  616. if reslen < len then
  617. reslen:=len;
  618. if r > 0 then
  619. begin
  620. reslen:=len;
  621. point:=tlen - r;
  622. end
  623. else
  624. point:=tlen;
  625. end
  626. else
  627. begin
  628. { fixed format }
  629. Inc(reslen, sign);
  630. { prepending fractional part with zeroes }
  631. while tlen < 5 do
  632. begin
  633. Inc(reslen);
  634. Inc(tlen);
  635. buf[tlen]:='0';
  636. end;
  637. { Currency have 4 digits in fractional part }
  638. r:=4 - f;
  639. point:=f;
  640. if point <> 0 then
  641. begin
  642. if point > 4 then
  643. point:=4;
  644. Inc(point);
  645. end;
  646. Dec(reslen,r);
  647. end;
  648. { rounding string if r > 0 }
  649. if r > 0 then
  650. begin
  651. k := 0;
  652. i := r+2;
  653. if i > tlen then
  654. i := tlen+1;
  655. if buf[i-2] >= '5' then
  656. begin
  657. if buf[i-1] < '9' then
  658. buf[i-1] := chr(ord(buf[i-1])+1)
  659. else
  660. begin
  661. buf[i-1] := '0';
  662. k := 1;
  663. end;
  664. end;
  665. If (k=1) and (buf[i-1]='0') then
  666. begin
  667. { 1.9996 rounded to two decimal digits after the decimal separator must result in
  668. 2.00, i.e. the rounding is propagated
  669. }
  670. while buf[i]='9' do
  671. begin
  672. buf[i]:='0';
  673. inc(i);
  674. end;
  675. buf[i]:=chr(Ord(buf[i])+1);
  676. { did we add another digit? This happens when rounding
  677. e.g. 99.9996 to two decimal digits after the decimal separator which should result in
  678. 100.00
  679. }
  680. if i>tlen then
  681. begin
  682. inc(reslen);
  683. inc(tlen);
  684. end;
  685. end;
  686. end;
  687. { preparing result string }
  688. if reslen<len then
  689. reslen:=len;
  690. if reslen>High(s) then
  691. begin
  692. if r < 0 then
  693. Inc(r, reslen - High(s));
  694. reslen:=High(s);
  695. end;
  696. SetLength(s,reslen);
  697. j:=reslen;
  698. if f<0 then
  699. begin
  700. { writing power of 10 part }
  701. if PInt64(@c)^ = 0 then
  702. k:=0
  703. else
  704. k:=tlen-5;
  705. if k >= 0 then
  706. s[j-2]:='+'
  707. else
  708. begin
  709. s[j-2]:='-';
  710. k:=-k;
  711. end;
  712. s[j]:=Chr(k mod 10 + $30);
  713. Dec(j);
  714. s[j]:=Chr(k div 10 + $30);
  715. Dec(j,2);
  716. s[j]:='E';
  717. Dec(j);
  718. end;
  719. { writing extra zeroes if r < 0 }
  720. while r < 0 do
  721. begin
  722. s[j]:='0';
  723. Dec(j);
  724. Inc(r);
  725. end;
  726. { writing digits and decimal point }
  727. for i:=r + 1 to tlen do
  728. begin
  729. Dec(point);
  730. if point = 0 then
  731. begin
  732. s[j]:='.';
  733. Dec(j);
  734. end;
  735. s[j]:=buf[i];
  736. Dec(j);
  737. end;
  738. { writing sign }
  739. if sign = 1 then
  740. begin
  741. s[j]:='-';
  742. Dec(j);
  743. end;
  744. { writing spaces }
  745. while j > 0 do
  746. begin
  747. s[j]:=' ';
  748. Dec(j);
  749. end;
  750. end;
  751. {
  752. Array Of Char Str() helpers
  753. }
  754. procedure fpc_chararray_sint(v : valsint;len : SizeInt;out a:array of char);compilerproc;
  755. var
  756. ss : shortstring;
  757. maxlen : SizeInt;
  758. begin
  759. int_str(v,ss);
  760. if length(ss)<len then
  761. ss:=space(len-length(ss))+ss;
  762. if length(ss)<high(a)+1 then
  763. maxlen:=length(ss)
  764. else
  765. maxlen:=high(a)+1;
  766. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  767. end;
  768. procedure fpc_chararray_uint(v : valuint;len : SizeInt;out a : array of char);compilerproc;
  769. var
  770. ss : shortstring;
  771. maxlen : SizeInt;
  772. begin
  773. int_str_unsigned(v,ss);
  774. if length(ss)<len then
  775. ss:=space(len-length(ss))+ss;
  776. if length(ss)<high(a)+1 then
  777. maxlen:=length(ss)
  778. else
  779. maxlen:=high(a)+1;
  780. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  781. end;
  782. {$ifndef CPU64}
  783. procedure fpc_chararray_qword(v : qword;len : SizeInt;out a : array of char);compilerproc;
  784. {$ifdef EXCLUDE_COMPLEX_PROCS}
  785. begin
  786. runerror(219);
  787. end;
  788. {$else EXCLUDE_COMPLEX_PROCS}
  789. var
  790. ss : shortstring;
  791. maxlen : SizeInt;
  792. begin
  793. int_str_unsigned(v,ss);
  794. if length(ss)<len then
  795. ss:=space(len-length(ss))+ss;
  796. if length(ss)<high(a)+1 then
  797. maxlen:=length(ss)
  798. else
  799. maxlen:=high(a)+1;
  800. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  801. end;
  802. {$endif EXCLUDE_COMPLEX_PROCS}
  803. procedure fpc_chararray_int64(v : int64;len : SizeInt;out a : array of char);compilerproc;
  804. {$ifdef EXCLUDE_COMPLEX_PROCS}
  805. begin
  806. runerror(219);
  807. end;
  808. {$else EXCLUDE_COMPLEX_PROCS}
  809. var
  810. ss : shortstring;
  811. maxlen : SizeInt;
  812. begin
  813. int_str(v,ss);
  814. if length(ss)<len then
  815. ss:=space(len-length(ss))+ss;
  816. if length(ss)<high(a)+1 then
  817. maxlen:=length(ss)
  818. else
  819. maxlen:=high(a)+1;
  820. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  821. end;
  822. {$endif EXCLUDE_COMPLEX_PROCS}
  823. {$endif CPU64}
  824. {$if defined(CPU16) or defined(CPU8)}
  825. procedure fpc_chararray_longword(v : longword;len : SizeInt;out a : array of char);compilerproc;
  826. var
  827. ss : shortstring;
  828. maxlen : SizeInt;
  829. begin
  830. int_str_unsigned(v,ss);
  831. if length(ss)<len then
  832. ss:=space(len-length(ss))+ss;
  833. if length(ss)<high(a)+1 then
  834. maxlen:=length(ss)
  835. else
  836. maxlen:=high(a)+1;
  837. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  838. end;
  839. procedure fpc_chararray_longint(v : longint;len : SizeInt;out a : array of char);compilerproc;
  840. var
  841. ss : shortstring;
  842. maxlen : SizeInt;
  843. begin
  844. int_str(v,ss);
  845. if length(ss)<len then
  846. ss:=space(len-length(ss))+ss;
  847. if length(ss)<high(a)+1 then
  848. maxlen:=length(ss)
  849. else
  850. maxlen:=high(a)+1;
  851. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  852. end;
  853. procedure fpc_chararray_word(v : word;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_smallint(v : smallint;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. {$endif CPU16 or CPU8}
  882. {$ifndef FPUNONE}
  883. procedure fpc_chararray_Float(d : ValReal;len,fr,rt : SizeInt;out a : array of char);compilerproc;
  884. var
  885. ss : shortstring;
  886. maxlen : SizeInt;
  887. begin
  888. str_real(len,fr,d,treal_type(rt),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. {$endif}
  896. {$ifndef FPC_STR_ENUM_INTERN}
  897. { currently, the avr code generator fails on this procedure, so we disable it,
  898. this is not a good solution but fixing compilation of this procedure for
  899. avr is hard, requires significant changes to the register allocator to take
  900. care of different register classes }
  901. procedure fpc_chararray_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out a : array of char);compilerproc;
  902. var
  903. ss : shortstring;
  904. maxlen : SizeInt;
  905. begin
  906. {$ifdef EXCLUDE_COMPLEX_PROCS}
  907. runerror(219);
  908. {$else EXCLUDE_COMPLEX_PROCS}
  909. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  910. if length(ss)<high(a)+1 then
  911. maxlen:=length(ss)
  912. else
  913. maxlen:=high(a)+1;
  914. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  915. {$endif EXCLUDE_COMPLEX_PROCS}
  916. end;
  917. {$endif not FPC_STR_ENUM_INTERN}
  918. procedure fpc_chararray_bool(b : boolean;len:sizeint;out a : array of char);compilerproc;
  919. var
  920. ss : shortstring;
  921. maxlen : SizeInt;
  922. begin
  923. fpc_shortstr_bool(b,len,ss);
  924. if length(ss)<high(a)+1 then
  925. maxlen:=length(ss)
  926. else
  927. maxlen:=high(a)+1;
  928. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  929. end;
  930. {$ifndef FPC_HAS_CHARARRAY_CURRENCY}
  931. {$define FPC_HAS_CHARARRAY_CURRENCY}
  932. procedure fpc_chararray_Currency(c : Currency;len,fr : SizeInt;out a : array of char);compilerproc;
  933. {$ifdef EXCLUDE_COMPLEX_PROCS}
  934. begin
  935. runerror(217);
  936. end;
  937. {$else EXCLUDE_COMPLEX_PROCS}
  938. var
  939. ss : shortstring;
  940. maxlen : SizeInt;
  941. begin
  942. str(c:len:fr,ss);
  943. if length(ss)<high(a)+1 then
  944. maxlen:=length(ss)
  945. else
  946. maxlen:=high(a)+1;
  947. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  948. end;
  949. {$endif EXCLUDE_COMPLEX_PROCS}
  950. {$endif FPC_HAS_STR_CURRENCY}
  951. {*****************************************************************************
  952. Val() Functions
  953. *****************************************************************************}
  954. Function InitVal(const s:shortstring;out negativ:boolean;out base:byte):ValSInt;
  955. var
  956. Code : SizeInt;
  957. begin
  958. code:=1;
  959. negativ:=false;
  960. base:=10;
  961. if length(s)=0 then
  962. begin
  963. InitVal:=code;
  964. Exit;
  965. end;
  966. {Skip Spaces and Tab}
  967. while (code<=length(s)) and (s[code] in [' ',#9]) do
  968. inc(code);
  969. {Sign}
  970. case s[code] of
  971. '-' : begin
  972. negativ:=true;
  973. inc(code);
  974. end;
  975. '+' : inc(code);
  976. end;
  977. {Base}
  978. if code<=length(s) then
  979. begin
  980. case s[code] of
  981. '$',
  982. 'X',
  983. 'x' : begin
  984. base:=16;
  985. inc(code);
  986. end;
  987. '%' : begin
  988. base:=2;
  989. inc(code);
  990. end;
  991. '&' : begin
  992. Base:=8;
  993. inc(code);
  994. end;
  995. '0' : begin
  996. if (code < length(s)) and (s[code+1] in ['x', 'X']) then
  997. begin
  998. inc(code, 2);
  999. base := 16;
  1000. end;
  1001. end;
  1002. end;
  1003. end;
  1004. { strip leading zeros }
  1005. while ((code < length(s)) and (s[code] = '0')) do begin
  1006. inc(code);
  1007. end;
  1008. InitVal:=code;
  1009. end;
  1010. Function fpc_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; compilerproc;
  1011. var
  1012. temp, prev, maxPrevValue, maxNewValue: ValUInt;
  1013. base,u : byte;
  1014. negative : boolean;
  1015. begin
  1016. fpc_Val_SInt_ShortStr := 0;
  1017. Temp:=0;
  1018. Code:=InitVal(s,negative,base);
  1019. if Code>length(s) then
  1020. exit;
  1021. if (s[Code]=#0) then
  1022. begin
  1023. if (Code>1) and (s[Code-1]='0') then
  1024. Code:=0;
  1025. exit;
  1026. end;
  1027. maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  1028. if (base = 10) then
  1029. maxNewValue := MaxSIntValue + ord(negative)
  1030. else
  1031. maxNewValue := MaxUIntValue;
  1032. while Code<=Length(s) do
  1033. begin
  1034. case s[Code] of
  1035. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1036. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1037. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1038. #0 : break;
  1039. else
  1040. u:=16;
  1041. end;
  1042. Prev := Temp;
  1043. Temp := Temp*ValUInt(base);
  1044. If (u >= base) or
  1045. (ValUInt(maxNewValue-u) < Temp) or
  1046. (prev > maxPrevValue) Then
  1047. Begin
  1048. fpc_Val_SInt_ShortStr := 0;
  1049. Exit
  1050. End;
  1051. Temp:=Temp+u;
  1052. inc(code);
  1053. end;
  1054. code := 0;
  1055. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  1056. If Negative Then
  1057. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  1058. If Not(Negative) and (base <> 10) Then
  1059. {sign extend the result to allow proper range checking}
  1060. Case DestSize of
  1061. 1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
  1062. 2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
  1063. {$ifdef cpu64}
  1064. 4: fpc_Val_SInt_ShortStr := longint(fpc_Val_SInt_ShortStr);
  1065. {$endif cpu64}
  1066. End;
  1067. end;
  1068. {$ifndef FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1069. {$define FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1070. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  1071. { we have to pass the DestSize parameter on (JM) }
  1072. Function int_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  1073. {$endif FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1074. Function fpc_Val_UInt_Shortstr(Const S: ShortString; out Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; compilerproc;
  1075. var
  1076. base,u : byte;
  1077. negative : boolean;
  1078. begin
  1079. fpc_Val_UInt_Shortstr:=0;
  1080. Code:=InitVal(s,negative,base);
  1081. If Negative or (Code>length(s)) Then
  1082. Exit;
  1083. if (s[Code]=#0) then
  1084. begin
  1085. if (Code>1) and (s[Code-1]='0') then
  1086. Code:=0;
  1087. exit;
  1088. end;
  1089. while Code<=Length(s) do
  1090. begin
  1091. case s[Code] of
  1092. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1093. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1094. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1095. #0 : break;
  1096. else
  1097. u:=16;
  1098. end;
  1099. If (u>=base) or
  1100. (ValUInt(MaxUIntValue-u) div ValUInt(Base)<fpc_val_uint_shortstr) then
  1101. begin
  1102. fpc_Val_UInt_Shortstr:=0;
  1103. exit;
  1104. end;
  1105. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
  1106. inc(code);
  1107. end;
  1108. code := 0;
  1109. end;
  1110. {$ifndef CPU64}
  1111. Function fpc_val_int64_shortstr(Const S: ShortString; out Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR']; compilerproc;
  1112. var u : sizeuint;
  1113. temp, prev, maxprevvalue, maxnewvalue : qword;
  1114. base : byte;
  1115. negative : boolean;
  1116. const maxint64=qword($7fffffffffffffff);
  1117. maxqword=qword($ffffffffffffffff);
  1118. begin
  1119. {$ifdef EXCLUDE_COMPLEX_PROCS}
  1120. runerror(219);
  1121. {$else EXCLUDE_COMPLEX_PROCS}
  1122. fpc_val_int64_shortstr := 0;
  1123. Temp:=0;
  1124. Code:=InitVal(s,negative,base);
  1125. if Code>length(s) then
  1126. exit;
  1127. if (s[Code]=#0) then
  1128. begin
  1129. if (Code>1) and (s[Code-1]='0') then
  1130. Code:=0;
  1131. exit;
  1132. end;
  1133. maxprevvalue := maxqword div base;
  1134. if (base = 10) then
  1135. maxnewvalue := maxint64 + ord(negative)
  1136. else
  1137. maxnewvalue := maxqword;
  1138. while Code<=Length(s) do
  1139. begin
  1140. case s[Code] of
  1141. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1142. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1143. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1144. #0 : break;
  1145. else
  1146. u:=16;
  1147. end;
  1148. Prev:=Temp;
  1149. Temp:=Temp*qword(base);
  1150. If (u >= base) or
  1151. (qword(maxnewvalue-u) < temp) or
  1152. (prev > maxprevvalue) Then
  1153. Begin
  1154. fpc_val_int64_shortstr := 0;
  1155. Exit
  1156. End;
  1157. Temp:=Temp+u;
  1158. inc(code);
  1159. end;
  1160. code:=0;
  1161. fpc_val_int64_shortstr:=int64(Temp);
  1162. If Negative Then
  1163. fpc_val_int64_shortstr:=-fpc_val_int64_shortstr;
  1164. {$endif EXCLUDE_COMPLEX_PROCS}
  1165. end;
  1166. Function fpc_val_qword_shortstr(Const S: ShortString; out Code: ValSInt): QWord; [public, alias:'FPC_VAL_QWORD_SHORTSTR']; compilerproc;
  1167. var u : sizeuint;
  1168. base : byte;
  1169. negative : boolean;
  1170. const maxqword=qword($ffffffffffffffff);
  1171. begin
  1172. fpc_val_qword_shortstr:=0;
  1173. Code:=InitVal(s,negative,base);
  1174. If Negative or (Code>length(s)) Then
  1175. Exit;
  1176. if (s[Code]=#0) then
  1177. begin
  1178. if (Code>1) and (s[Code-1]='0') then
  1179. Code:=0;
  1180. exit;
  1181. end;
  1182. while Code<=Length(s) do
  1183. begin
  1184. case s[Code] of
  1185. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1186. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1187. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1188. #0 : break;
  1189. else
  1190. u:=16;
  1191. end;
  1192. If (u>=base) or
  1193. ((QWord(maxqword-u) div QWord(base))<fpc_val_qword_shortstr) then
  1194. Begin
  1195. fpc_val_qword_shortstr := 0;
  1196. Exit
  1197. End;
  1198. fpc_val_qword_shortstr:=fpc_val_qword_shortstr*QWord(base) + u;
  1199. inc(code);
  1200. end;
  1201. code := 0;
  1202. end;
  1203. {$endif CPU64}
  1204. {$if defined(CPU16) or defined(CPU8)}
  1205. Function fpc_val_longint_shortstr(Const S: ShortString; out Code: ValSInt): LongInt; [public, alias:'FPC_VAL_LONGINT_SHORTSTR']; compilerproc;
  1206. var u, temp, prev, maxprevvalue, maxnewvalue : longword;
  1207. base : byte;
  1208. negative : boolean;
  1209. const maxlongint=longword($7fffffff);
  1210. maxlongword=longword($ffffffff);
  1211. begin
  1212. fpc_val_longint_shortstr := 0;
  1213. Temp:=0;
  1214. Code:=InitVal(s,negative,base);
  1215. if Code>length(s) then
  1216. exit;
  1217. if (s[Code]=#0) then
  1218. begin
  1219. if (Code>1) and (s[Code-1]='0') then
  1220. Code:=0;
  1221. exit;
  1222. end;
  1223. maxprevvalue := maxlongword div base;
  1224. if (base = 10) then
  1225. maxnewvalue := maxlongint + ord(negative)
  1226. else
  1227. maxnewvalue := maxlongword;
  1228. while Code<=Length(s) do
  1229. begin
  1230. case s[Code] of
  1231. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1232. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1233. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1234. #0 : break;
  1235. else
  1236. u:=16;
  1237. end;
  1238. Prev:=Temp;
  1239. Temp:=Temp*longword(base);
  1240. If (u >= base) or
  1241. (longword(maxnewvalue-u) < temp) or
  1242. (prev > maxprevvalue) Then
  1243. Begin
  1244. fpc_val_longint_shortstr := 0;
  1245. Exit
  1246. End;
  1247. Temp:=Temp+u;
  1248. inc(code);
  1249. end;
  1250. code:=0;
  1251. fpc_val_longint_shortstr:=longint(Temp);
  1252. If Negative Then
  1253. fpc_val_longint_shortstr:=-fpc_val_longint_shortstr;
  1254. end;
  1255. Function fpc_val_longword_shortstr(Const S: ShortString; out Code: ValSInt): LongWord; [public, alias:'FPC_VAL_LONGWORD_SHORTSTR']; compilerproc;
  1256. var u, prev: LongWord;
  1257. base : byte;
  1258. negative : boolean;
  1259. const maxlongword=longword($ffffffff);
  1260. begin
  1261. fpc_val_longword_shortstr:=0;
  1262. Code:=InitVal(s,negative,base);
  1263. If Negative or (Code>length(s)) Then
  1264. Exit;
  1265. if (s[Code]=#0) then
  1266. begin
  1267. if (Code>1) and (s[Code-1]='0') then
  1268. Code:=0;
  1269. exit;
  1270. end;
  1271. while Code<=Length(s) do
  1272. begin
  1273. case s[Code] of
  1274. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1275. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1276. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1277. #0 : break;
  1278. else
  1279. u:=16;
  1280. end;
  1281. prev := fpc_val_longword_shortstr;
  1282. If (u>=base) or
  1283. ((LongWord(maxlongword-u) div LongWord(base))<prev) then
  1284. Begin
  1285. fpc_val_longword_shortstr := 0;
  1286. Exit
  1287. End;
  1288. fpc_val_longword_shortstr:=fpc_val_longword_shortstr*LongWord(base) + u;
  1289. inc(code);
  1290. end;
  1291. code := 0;
  1292. end;
  1293. Function fpc_val_smallint_shortstr(Const S: ShortString; out Code: ValSInt): SmallInt; [public, alias:'FPC_VAL_SMALLINT_SHORTSTR']; compilerproc;
  1294. var u, temp, prev, maxprevvalue, maxnewvalue : word;
  1295. base : byte;
  1296. negative : boolean;
  1297. const maxlongint=longword($7fffffff);
  1298. maxlongword=longword($ffffffff);
  1299. begin
  1300. fpc_val_smallint_shortstr := 0;
  1301. Temp:=0;
  1302. Code:=InitVal(s,negative,base);
  1303. if Code>length(s) then
  1304. exit;
  1305. if (s[Code]=#0) then
  1306. begin
  1307. if (Code>1) and (s[Code-1]='0') then
  1308. Code:=0;
  1309. exit;
  1310. end;
  1311. maxprevvalue := maxlongword div base;
  1312. if (base = 10) then
  1313. maxnewvalue := maxlongint + ord(negative)
  1314. else
  1315. maxnewvalue := maxlongword;
  1316. while Code<=Length(s) do
  1317. begin
  1318. case s[Code] of
  1319. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1320. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1321. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1322. #0 : break;
  1323. else
  1324. u:=16;
  1325. end;
  1326. Prev:=Temp;
  1327. Temp:=Temp*longword(base);
  1328. If (u >= base) or
  1329. (longword(maxnewvalue-u) < temp) or
  1330. (prev > maxprevvalue) Then
  1331. Begin
  1332. fpc_val_smallint_shortstr := 0;
  1333. Exit
  1334. End;
  1335. Temp:=Temp+u;
  1336. inc(code);
  1337. end;
  1338. code:=0;
  1339. fpc_val_smallint_shortstr:=longint(Temp);
  1340. If Negative Then
  1341. fpc_val_smallint_shortstr:=-fpc_val_smallint_shortstr;
  1342. end;
  1343. Function fpc_val_word_shortstr(Const S: ShortString; out Code: ValSInt): Word; [public, alias:'FPC_VAL_WORD_SHORTSTR']; compilerproc;
  1344. var u, prev: word;
  1345. base : byte;
  1346. negative : boolean;
  1347. const maxlongword=longword($ffffffff);
  1348. begin
  1349. fpc_val_word_shortstr:=0;
  1350. Code:=InitVal(s,negative,base);
  1351. If Negative or (Code>length(s)) Then
  1352. Exit;
  1353. if (s[Code]=#0) then
  1354. begin
  1355. if (Code>1) and (s[Code-1]='0') then
  1356. Code:=0;
  1357. exit;
  1358. end;
  1359. while Code<=Length(s) do
  1360. begin
  1361. case s[Code] of
  1362. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1363. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1364. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1365. #0 : break;
  1366. else
  1367. u:=16;
  1368. end;
  1369. prev := fpc_val_word_shortstr;
  1370. If (u>=base) or
  1371. ((LongWord(maxlongword-u) div LongWord(base))<prev) then
  1372. Begin
  1373. fpc_val_word_shortstr := 0;
  1374. Exit
  1375. End;
  1376. fpc_val_word_shortstr:=fpc_val_word_shortstr*LongWord(base) + u;
  1377. inc(code);
  1378. end;
  1379. code := 0;
  1380. end;
  1381. {$endif CPU16 or CPU8}
  1382. {$ifdef FLOAT_ASCII_FALLBACK}
  1383. {$ifndef FPUNONE}
  1384. const
  1385. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1386. valmaxexpnorm=4932;
  1387. mantissabits=64;
  1388. {$else}
  1389. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1390. valmaxexpnorm=308;
  1391. mantissabits=53;
  1392. {$else}
  1393. {$ifdef FPC_HAS_TYPE_SINGLE}
  1394. valmaxexpnorm=38;
  1395. mantissabits=24;
  1396. {$else}
  1397. {$error Unknown floating point precision }
  1398. {$endif}
  1399. {$endif}
  1400. {$endif}
  1401. {$endif}
  1402. {$ifndef FPUNONE}
  1403. (******************
  1404. Derived from: ".\Free Pascal\source\rtl\inc\genmath.inc"
  1405. Origin: "fast 10^n routine"
  1406. function FPower10(val: Extended; Power: Longint): Extended;
  1407. Changes:
  1408. > adapted to "ValReal", so float can be single/double/extended
  1409. > slightly changed arrays [redundant 58+2 float constants gone away]
  1410. > added some checks etc..
  1411. Notes:
  1412. > denormalization and overflow should go smooth if corresponding
  1413. FPU exceptions are masked [no external care needed by now]
  1414. > adaption to real48 and real128 is not hard if one needed
  1415. ******************)
  1416. //
  1417. function mul_by_power10(x:ValReal;power:integer):ValReal;
  1418. //
  1419. // result:=X*(10^power)
  1420. //
  1421. // Routine achieves result with no more than 3 floating point mul/div's.
  1422. // Up to ABS(power)=31, only 1 floating point mul/div is needed.
  1423. //
  1424. // Limitations:
  1425. // for ValReal=extended : power=-5119..+5119
  1426. // for ValReal=double : power=-319..+319
  1427. // for ValReal=single : power=-63..+63
  1428. //
  1429. // If "power" is beyond this limits, routine gives up and returns 0/+INF/-INF.
  1430. // This is not generally correct, but should be ok when routine is used only
  1431. // as "VAL"-helper, since "x" exponent is reasonably close to 0 in this case.
  1432. //
  1433. //==================================
  1434. {$IF DECLARED(C_HIGH_EXPBITS_5TO8)}
  1435. {$ERROR C_HIGH_EXPBITS_5TO8 declared somewhere in scope}
  1436. {$ENDIF}
  1437. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)}
  1438. {$ERROR C_HIGH_EXPBITS_9ANDUP declared somewhere in scope}
  1439. {$ENDIF}
  1440. {$IF SIZEOF(ValReal)=10}
  1441. //==================================
  1442. // assuming "type ValReal=extended;"
  1443. //
  1444. const
  1445. C_MAX_POWER = 5119;
  1446. C_HIGH_EXPBITS_5TO8 = 15;
  1447. C_HIGH_EXPBITS_9ANDUP = 9;
  1448. {$ELSEIF SIZEOF(ValReal)=8}
  1449. //==================================
  1450. // assuming "type ValReal=double;"
  1451. //
  1452. const
  1453. C_MAX_POWER = 319;
  1454. C_HIGH_EXPBITS_5TO8 = 9;
  1455. {$ELSEIF SIZEOF(ValReal)=4}
  1456. //==================================
  1457. // assuming "type ValReal=single;"
  1458. //
  1459. const
  1460. C_MAX_POWER = 63;
  1461. {$ELSE}
  1462. //==================================
  1463. // assuming "ValReal=?"
  1464. //
  1465. {$ERROR Unsupported ValReal type}
  1466. {$ENDIF}
  1467. //==================================
  1468. const
  1469. C_INFTYP = ValReal( 1.0/0.0);
  1470. C_INFTYM = ValReal(-1.0/0.0);
  1471. mul_expbits_0_to_4:packed array[0..31]of ValReal=(
  1472. 1E0, 1E1, 1E2, 1E3,
  1473. 1E4, 1E5, 1E6, 1E7,
  1474. 1E8, 1E9, 1E10, 1E11,
  1475. 1E12, 1E13, 1E14, 1E15,
  1476. 1E16, 1E17, 1E18, 1E19,
  1477. 1E20, 1E21, 1E22, 1E23,
  1478. 1E24, 1E25, 1E26, 1E27,
  1479. 1E28, 1E29, 1E30, 1E31);
  1480. {$IF DECLARED(C_HIGH_EXPBITS_5TO8)}
  1481. mul_expbits_5_to_8:packed array[1..C_HIGH_EXPBITS_5TO8] of ValReal=(
  1482. 1E32, 1E64, 1E96, 1E128,
  1483. 1E160, 1E192, 1E224, 1E256, 1E288
  1484. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)},
  1485. 1E320, 1E352, 1E384, 1E416, 1E448, 1E480
  1486. {$ENDIF});
  1487. {$ELSE}
  1488. mul_expbits_5_to_8:ValReal=1E32;
  1489. {$ENDIF}
  1490. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)}
  1491. mul_expbits_9_and_up:packed array[1..C_HIGH_EXPBITS_9ANDUP] of ValReal=(
  1492. 1E512, 1E1024, 1E1536, 1E2048,
  1493. 1E2560, 1E3072, 1E3584, 1E4096,
  1494. 1E4608);
  1495. {$ENDIF}
  1496. begin
  1497. if power=0 then mul_by_power10:=x else
  1498. if power<-C_MAX_POWER then mul_by_power10:=0 else
  1499. if power>C_MAX_POWER then
  1500. if x<0 then mul_by_power10:=C_INFTYM else
  1501. if x>0 then mul_by_power10:=C_INFTYP else mul_by_power10:=0
  1502. else
  1503. if power<0 then
  1504. begin
  1505. power:=-power;
  1506. mul_by_power10:=x/mul_expbits_0_to_4[power and $1F];
  1507. power:=(power shr 5);
  1508. if power=0 then exit;
  1509. {$IF DECLARED(C_HIGH_EXPBITS_5TO8)}
  1510. if power and $F<>0 then
  1511. mul_by_power10:=
  1512. mul_by_power10/mul_expbits_5_to_8[power and $F];
  1513. {$ELSE} // "single", power<>0, so always div
  1514. mul_by_power10:=mul_by_power10/mul_expbits_5_to_8;
  1515. {$ENDIF}
  1516. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)}
  1517. power:=(power shr 4);
  1518. if power<>0 then
  1519. mul_by_power10:=
  1520. mul_by_power10/mul_expbits_9_and_up[power];
  1521. {$ENDIF}
  1522. end
  1523. else
  1524. begin
  1525. mul_by_power10:=x*mul_expbits_0_to_4[power and $1F];
  1526. power:=(power shr 5);
  1527. if power=0 then exit;
  1528. {$IF DECLARED(C_HIGH_EXPBITS_5TO8)}
  1529. if power and $F<>0 then
  1530. mul_by_power10:=
  1531. mul_by_power10*mul_expbits_5_to_8[power and $F];
  1532. {$ELSE} // "single", power<>0, so always mul
  1533. mul_by_power10:=mul_by_power10*mul_expbits_5_to_8;
  1534. {$ENDIF}
  1535. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)}
  1536. power:=(power shr 4);
  1537. if power<>0 then
  1538. mul_by_power10:=
  1539. mul_by_power10*mul_expbits_9_and_up[power];
  1540. {$ENDIF}
  1541. end;
  1542. end;
  1543. Function fpc_Val_Real_ShortStr(const s : shortstring; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; compilerproc;
  1544. var
  1545. hd,
  1546. sign : valreal;
  1547. esign,
  1548. exponent,
  1549. expstart,
  1550. decpoint : SizeInt;
  1551. nint,
  1552. nlz,
  1553. explimit,
  1554. explastdigit: SizeInt;
  1555. begin
  1556. fpc_Val_Real_ShortStr:=0.0;
  1557. code:=1;
  1558. exponent:=0;
  1559. decpoint:=0;
  1560. esign:=1;
  1561. hd:=0.0;
  1562. nlz:=0;
  1563. nint:=0;
  1564. sign:=1;
  1565. while (code<=length(s)) and (s[code] in [' ',#9]) do
  1566. inc(code);
  1567. if code<=length(s) then
  1568. case s[code] of
  1569. '+' : inc(code);
  1570. '-' : begin
  1571. sign:=-1;
  1572. inc(code);
  1573. end;
  1574. end;
  1575. { leading zeroes do not influence result, skip all but one of them }
  1576. expstart:=code;
  1577. while (code<Length(s)) and (s[code]='0') do
  1578. inc(code);
  1579. if (code>expstart) then
  1580. dec(code);
  1581. expstart:=code;
  1582. while (Code<=Length(s)) do
  1583. begin
  1584. case s[code] of
  1585. '0':
  1586. begin
  1587. if (hd=0) then
  1588. inc(nlz,ord(decpoint<>0))
  1589. else
  1590. inc(nint,ord(decpoint=0));
  1591. hd:=hd*10;
  1592. end;
  1593. '1'..'9':
  1594. begin
  1595. if (decpoint=0) then
  1596. inc(nint);
  1597. hd:=hd*10+(ord(s[code])-ord('0'));
  1598. end;
  1599. '.':
  1600. if decpoint=0 then
  1601. decpoint:=code
  1602. else
  1603. exit;
  1604. else
  1605. break;
  1606. end;
  1607. inc(code);
  1608. end;
  1609. { must have seen at least one digit }
  1610. if (code-expstart)<1+ord(decpoint<>0) then
  1611. exit;
  1612. if decpoint<>0 then
  1613. decpoint:=code-decpoint-1;
  1614. { Exponent ? }
  1615. if (length(s)>=code) and (s[code] in ['e','E']) then
  1616. begin
  1617. inc(code);
  1618. if Length(s) >= code then
  1619. case s[code] of
  1620. '+': inc(code);
  1621. '-': begin
  1622. esign:=-1;
  1623. inc(code);
  1624. end;
  1625. end;
  1626. expstart:=code;
  1627. { Limit the exponent, accounting for digits in integer part of mantissa
  1628. and leading zeros in fractional part, e.g 100.0e306 = 1.0e308, etc. }
  1629. if (esign<0) then
  1630. explimit:=valmaxexpnorm+mantissabits-1+nint
  1631. else if (nint>0) then
  1632. explimit:=valmaxexpnorm+1-nint
  1633. else
  1634. explimit:=valmaxexpnorm+1+nlz;
  1635. explastdigit:=(explimit mod 10)+ord('0');
  1636. explimit:=explimit div 10;
  1637. while (length(s)>=code) and (s[code] in ['0'..'9']) do
  1638. begin
  1639. { Check commented out: since this code is used by compiler, it would error out
  1640. e.g. if compiling '1e3000' for non-x86 target. OTOH silently treating it
  1641. as infinity isn't a good option either. }
  1642. (*
  1643. if (exponent>explimit) or
  1644. ((exponent=explimit) and (ord(s[code])>explastdigit)) then
  1645. begin
  1646. { ignore exponent overflow for zero mantissa }
  1647. if hd<>0.0 then
  1648. exit;
  1649. end
  1650. else *)
  1651. exponent:=exponent*10+(ord(s[code])-ord('0'));
  1652. inc(code);
  1653. end;
  1654. if code=expstart then
  1655. exit;
  1656. end;
  1657. { Not all characters are read ? }
  1658. if length(s)>=code then
  1659. exit;
  1660. { adjust exponent based on decimal point }
  1661. dec(exponent,decpoint*esign);
  1662. if (exponent<0) then
  1663. begin
  1664. esign:=-1;
  1665. exponent:=-exponent;
  1666. end;
  1667. { evaluate sign }
  1668. { (before exponent, because the exponent may turn it into a denormal) }
  1669. fpc_Val_Real_ShortStr:=hd*sign;
  1670. { Calculate Exponent }
  1671. hd:=1.0;
  1672. { the magnitude range maximum (normal) is lower in absolute value than the }
  1673. { the magnitude range minimum (denormal). E.g. an extended value can go }
  1674. { up to 1E4932, but "down" to 1E-4951. So make sure that we don't try to }
  1675. { calculate 1E4951 as factor, since that would overflow and result in 0. }
  1676. if (exponent>valmaxexpnorm-2) then
  1677. begin
  1678. hd:=mul_by_power10(hd,valmaxexpnorm-2);
  1679. if esign>0 then
  1680. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  1681. else
  1682. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  1683. dec(exponent,valmaxexpnorm-2);
  1684. hd:=1.0;
  1685. end;
  1686. hd:=mul_by_power10(hd,exponent);
  1687. if esign>0 then
  1688. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  1689. else
  1690. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  1691. { success ! }
  1692. code:=0;
  1693. end;
  1694. {$endif}
  1695. {$else not FLOAT_ASCII_FALLBACK}
  1696. {$ifndef FPUNONE}
  1697. Function fpc_Val_Real_ShortStr(const s : shortstring; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; compilerproc;
  1698. begin
  1699. fpc_Val_Real_ShortStr := val_real( s, code );
  1700. end;
  1701. {$endif FPUNONE}
  1702. {$endif FLOAT_ASCII_FALLBACK}
  1703. {$ifndef FPC_STR_ENUM_INTERN}
  1704. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint; [public, alias:'FPC_VAL_ENUM_SHORTSTR']; compilerproc;
  1705. function string_compare(const s1,s2:shortstring):sizeint;
  1706. {We cannot use the > and < operators to compare a string here, because we if the string is
  1707. not found in the enum, we need to return the position of error in "code". Code equals the
  1708. highest matching character of all string compares, which is only known inside the string
  1709. comparison.}
  1710. var i,l:byte;
  1711. c1,c2:char;
  1712. begin
  1713. l:=length(s1);
  1714. if length(s1)>length(s2) then
  1715. l:=length(s2);
  1716. i:=1;
  1717. while i<=l do
  1718. begin
  1719. c1:=s1[i];
  1720. c2:=s2[i];
  1721. if c1<>c2 then
  1722. break;
  1723. inc(i);
  1724. end;
  1725. if i>code then
  1726. code:=i;
  1727. if i<=l then
  1728. string_compare:=byte(c1)-byte(c2)
  1729. else
  1730. string_compare:=length(s1)-length(s2);
  1731. end;
  1732. type Psorted_array=^Tsorted_array;
  1733. Tsorted_array={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1734. o:longint;
  1735. s:Pstring;
  1736. end;
  1737. Pstring_to_ord=^Tstring_to_ord;
  1738. Tstring_to_ord={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1739. count:longint;
  1740. data:array[0..0] of Tsorted_array;
  1741. end;
  1742. var l,h,m:cardinal;
  1743. c:sizeint;
  1744. sorted_array:^Tsorted_array;
  1745. spaces:byte;
  1746. t:shortstring;
  1747. begin
  1748. {Val for numbers accepts spaces at the start, so lets do the same
  1749. for enums. Skip spaces at the start of the string.}
  1750. spaces:=1;
  1751. code:=1;
  1752. while (spaces<=length(s)) and (s[spaces]=' ') do
  1753. inc(spaces);
  1754. t:=upcase(copy(s,spaces,255));
  1755. sorted_array:=pointer(@Pstring_to_ord(str2ordindex)^.data);
  1756. {Use a binary search to get the string.}
  1757. l:=1;
  1758. h:=Pstring_to_ord(str2ordindex)^.count;
  1759. repeat
  1760. m:=(l+h) div 2;
  1761. c:=string_compare(t,upcase(sorted_array[m-1].s^));
  1762. if c>0 then
  1763. l:=m+1
  1764. else if c<0 then
  1765. h:=m-1
  1766. else
  1767. break;
  1768. if l>h then
  1769. begin
  1770. {Not found...}
  1771. inc(code,spaces-1); {Add skipped spaces again.}
  1772. {The result of val in case of error is undefined, don't assign a function result.}
  1773. exit;
  1774. end;
  1775. until false;
  1776. code:=0;
  1777. fpc_val_enum_shortstr:=sorted_array[m-1].o;
  1778. end;
  1779. {Redeclare fpc_val_enum_shortstr for internal use in the system unit.}
  1780. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint;external name 'FPC_VAL_ENUM_SHORTSTR';
  1781. {$endif FPC_STR_ENUM_INTERN}
  1782. function fpc_Val_Currency_ShortStr(const s : shortstring; out Code : ValSInt): currency; [public, alias:'FPC_VAL_CURRENCY_SHORTSTR']; compilerproc;
  1783. {$ifdef EXCLUDE_COMPLEX_PROCS}
  1784. begin
  1785. runerror(217);
  1786. end;
  1787. {$else EXCLUDE_COMPLEX_PROCS}
  1788. const
  1789. MaxInt64 : Int64 = $7FFFFFFFFFFFFFFF;
  1790. Int64Edge : Int64 = ($7FFFFFFFFFFFFFFF - 10) div 10;
  1791. Int64Edge2 : Int64 = $7FFFFFFFFFFFFFFF div 10;
  1792. var
  1793. { to enable taking the address on the JVM target }
  1794. res : array[0..0] of Int64;
  1795. i,j,power,sign,len : longint;
  1796. FracOverflow : boolean;
  1797. begin
  1798. fpc_Val_Currency_ShortStr:=0;
  1799. res[0]:=0;
  1800. len:=Length(s);
  1801. Code:=1;
  1802. sign:=1;
  1803. power:=0;
  1804. while True do
  1805. if Code > len then
  1806. exit
  1807. else
  1808. if s[Code] in [' ', #9] then
  1809. Inc(Code)
  1810. else
  1811. break;
  1812. { Read sign }
  1813. case s[Code] of
  1814. '+' : Inc(Code);
  1815. '-' : begin
  1816. sign:=-1;
  1817. inc(code);
  1818. end;
  1819. end;
  1820. { Read digits }
  1821. FracOverflow:=False;
  1822. i:=0;
  1823. while Code <= len do
  1824. begin
  1825. case s[Code] of
  1826. '0'..'9':
  1827. begin
  1828. j:=Ord(s[code])-Ord('0');
  1829. { check overflow }
  1830. if (res[0] <= Int64Edge) or (res[0] <= (MaxInt64 - j) div 10) then
  1831. begin
  1832. res[0]:=res[0]*10 + j;
  1833. Inc(i);
  1834. end
  1835. else
  1836. if power = 0 then
  1837. { exit if integer part overflow }
  1838. exit
  1839. else
  1840. begin
  1841. if not FracOverflow and (j >= 5) and (res[0] < MaxInt64) then
  1842. { round if first digit of fractional part overflow }
  1843. Inc(res[0]);
  1844. FracOverflow:=True;
  1845. end;
  1846. end;
  1847. '.':
  1848. begin
  1849. if power = 0 then
  1850. begin
  1851. power:=1;
  1852. i:=0;
  1853. end
  1854. else
  1855. exit;
  1856. end;
  1857. else
  1858. break;
  1859. end;
  1860. Inc(Code);
  1861. end;
  1862. if (i = 0) and (power = 0) then
  1863. exit;
  1864. if power <> 0 then
  1865. power:=i;
  1866. power:=4 - power;
  1867. { Exponent? }
  1868. if Code <= len then
  1869. if s[Code] in ['E', 'e'] then
  1870. begin
  1871. Inc(Code);
  1872. if Code > len then
  1873. exit;
  1874. i:=1;
  1875. case s[Code] of
  1876. '+':
  1877. Inc(Code);
  1878. '-':
  1879. begin
  1880. i:=-1;
  1881. Inc(Code);
  1882. end;
  1883. end;
  1884. { read exponent }
  1885. j:=0;
  1886. while Code <= len do
  1887. if s[Code] in ['0'..'9'] then
  1888. begin
  1889. if j > 4951 then
  1890. exit;
  1891. j:=j*10 + (Ord(s[code])-Ord('0'));
  1892. Inc(Code);
  1893. end
  1894. else
  1895. exit;
  1896. power:=power + j*i;
  1897. end
  1898. else
  1899. exit;
  1900. if power > 0 then
  1901. begin
  1902. for i:=1 to power do
  1903. if res[0] <= Int64Edge2 then
  1904. res[0]:=res[0]*10
  1905. else
  1906. exit;
  1907. end
  1908. else
  1909. for i:=1 to -power do
  1910. begin
  1911. if res[0] <= MaxInt64 - 5 then
  1912. Inc(res[0], 5);
  1913. res[0]:=res[0] div 10;
  1914. end;
  1915. res[0]:=res[0]*sign;
  1916. fpc_Val_Currency_ShortStr:=PCurrency(@res[0])^;
  1917. Code:=0;
  1918. end;
  1919. {$endif EXCLUDE_COMPLEX_PROCS}
  1920. {$ifndef FPC_HAS_SETSTRING_SHORTSTR}
  1921. {$define FPC_HAS_SETSTRING_SHORTSTR}
  1922. 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}
  1923. begin
  1924. If Len > High(S) then
  1925. Len := High(S);
  1926. SetLength(S,Len);
  1927. If Buf<>Nil then
  1928. begin
  1929. Move (Buf[0],S[1],Len);
  1930. end;
  1931. end;
  1932. {$endif FPC_HAS_SETSTRING_SHORTSTR}
  1933. {$ifndef FPC_HAS_COMPARETEXT_SHORTSTR}
  1934. {$define FPC_HAS_COMPARETEXT_SHORTSTR}
  1935. function ShortCompareText(const S1, S2: shortstring): SizeInt;
  1936. var
  1937. c1, c2: Byte;
  1938. i: SizeInt;
  1939. L1, L2, Count: SizeInt;
  1940. P1, P2: PChar;
  1941. begin
  1942. L1 := Length(S1);
  1943. L2 := Length(S2);
  1944. if L1 > L2 then
  1945. Count := L2
  1946. else
  1947. Count := L1;
  1948. i := 0;
  1949. P1 := @S1[1];
  1950. P2 := @S2[1];
  1951. while i < count do
  1952. begin
  1953. c1 := byte(p1^);
  1954. c2 := byte(p2^);
  1955. if c1 <> c2 then
  1956. begin
  1957. if c1 in [97..122] then
  1958. Dec(c1, 32);
  1959. if c2 in [97..122] then
  1960. Dec(c2, 32);
  1961. if c1 <> c2 then
  1962. Break;
  1963. end;
  1964. Inc(P1); Inc(P2); Inc(I);
  1965. end;
  1966. if i < count then
  1967. ShortCompareText := c1 - c2
  1968. else
  1969. ShortCompareText := L1 - L2;
  1970. end;
  1971. {$endif FPC_HAS_COMPARETEXT_SHORTSTR}