sstrings.inc 55 KB

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