sstrings.inc 53 KB

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