sstrings.inc 54 KB

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