generic.inc 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  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. Processor independent implementation for the system unit
  5. (adapted for intel i386.inc file)
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {****************************************************************************
  13. Primitives
  14. ****************************************************************************}
  15. type
  16. pstring = ^shortstring;
  17. {$ifndef FPC_SYSTEM_HAS_MOVE}
  18. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE'];
  19. type
  20. bytearray = array [0..high(sizeint)-1] of byte;
  21. var
  22. i:longint;
  23. begin
  24. if count <= 0 then exit;
  25. Dec(count);
  26. if @source<@dest then
  27. begin
  28. for i:=count downto 0 do
  29. bytearray(dest)[i]:=bytearray(source)[i];
  30. end
  31. else
  32. begin
  33. for i:=0 to count do
  34. bytearray(dest)[i]:=bytearray(source)[i];
  35. end;
  36. end;
  37. {$endif not FPC_SYSTEM_HAS_MOVE}
  38. {$ifndef FPC_SYSTEM_HAS_FILLCHAR}
  39. Procedure FillChar(var x;count:SizeInt;value:byte);
  40. type
  41. longintarray = array [0..high(sizeint) div 4-1] of longint;
  42. bytearray = array [0..high(sizeint)-1] of byte;
  43. var
  44. i,v : longint;
  45. begin
  46. if count <= 0 then exit;
  47. v := 0;
  48. { aligned? }
  49. if (PtrUInt(@x) mod sizeof(PtrUInt))<>0 then
  50. begin
  51. for i:=0 to count-1 do
  52. bytearray(x)[i]:=value;
  53. end
  54. else
  55. begin
  56. v:=(value shl 8) or (value and $FF);
  57. v:=(v shl 16) or (v and $ffff);
  58. for i:=0 to (count div 4)-1 do
  59. longintarray(x)[i]:=v;
  60. for i:=(count div 4)*4 to count-1 do
  61. bytearray(x)[i]:=value;
  62. end;
  63. end;
  64. {$endif FPC_SYSTEM_HAS_FILLCHAR}
  65. {$ifndef FPC_SYSTEM_HAS_FILLBYTE}
  66. procedure FillByte (var x;count : SizeInt;value : byte );
  67. begin
  68. FillChar (X,Count,CHR(VALUE));
  69. end;
  70. {$endif not FPC_SYSTEM_HAS_FILLBYTE}
  71. {$ifndef FPC_SYSTEM_HAS_FILLWORD}
  72. procedure fillword(var x;count : SizeInt;value : word);
  73. type
  74. longintarray = array [0..high(sizeint) div 4-1] of longint;
  75. wordarray = array [0..high(sizeint) div 2-1] of word;
  76. var
  77. i,v : longint;
  78. begin
  79. if Count <= 0 then exit;
  80. { aligned? }
  81. if (PtrUInt(@x) mod sizeof(PtrUInt))<>0 then
  82. begin
  83. for i:=0 to count-1 do
  84. wordarray(x)[i]:=value;
  85. end
  86. else
  87. begin
  88. v:=value*$10000+value;
  89. for i:=0 to (count div 2) -1 do
  90. longintarray(x)[i]:=v;
  91. for i:=(count div 2)*2 to count-1 do
  92. wordarray(x)[i]:=value;
  93. end;
  94. end;
  95. {$endif not FPC_SYSTEM_HAS_FILLWORD}
  96. {$ifndef FPC_SYSTEM_HAS_FILLDWORD}
  97. procedure FillDWord(var x;count : SizeInt;value : DWord);
  98. type
  99. longintarray = array [0..high(sizeint) div 4-1] of longint;
  100. begin
  101. if count <= 0 then exit;
  102. while Count<>0 do
  103. begin
  104. { range checking must be disabled here }
  105. longintarray(x)[count-1]:=longint(value);
  106. Dec(count);
  107. end;
  108. end;
  109. {$endif FPC_SYSTEM_HAS_FILLDWORD}
  110. {$ifndef FPC_SYSTEM_HAS_INDEXCHAR}
  111. function IndexChar(Const buf;len:SizeInt;b:char):SizeInt;
  112. begin
  113. IndexChar:=IndexByte(Buf,Len,byte(B));
  114. end;
  115. {$endif not FPC_SYSTEM_HAS_INDEXCHAR}
  116. {$ifndef FPC_SYSTEM_HAS_INDEXBYTE}
  117. function IndexByte(Const buf;len:SizeInt;b:byte):SizeInt;
  118. type
  119. bytearray = array [0..high(sizeint)-1] of byte;
  120. var
  121. I : longint;
  122. begin
  123. I:=0;
  124. { simulate assembler implementations behaviour, which is expected }
  125. { fpc_pchar_to_ansistr in astrings.inc }
  126. if (len < 0) then
  127. len := high(longint);
  128. while (I<Len) and (bytearray(buf)[I]<>b) do
  129. inc(I);
  130. if (i=Len) then
  131. i:=-1; {Can't use 0, since it is a possible value}
  132. IndexByte:=I;
  133. end;
  134. {$endif not FPC_SYSTEM_HAS_INDEXBYTE}
  135. {$ifndef FPC_SYSTEM_HAS_INDEXWORD}
  136. function Indexword(Const buf;len:SizeInt;b:word):SizeInt;
  137. type
  138. wordarray = array [0..high(sizeint) div 2-1] of word;
  139. var
  140. I : longint;
  141. begin
  142. I:=0;
  143. if (len < 0) then
  144. len := high(longint);
  145. while (I<Len) and (wordarray(buf)[I]<>b) do
  146. inc(I);
  147. if (i=Len) then
  148. i:=-1; {Can't use 0, since it is a possible value for index}
  149. Indexword:=I;
  150. end;
  151. {$endif not FPC_SYSTEM_HAS_INDEXWORD}
  152. {$ifndef FPC_SYSTEM_HAS_INDEXDWORD}
  153. function IndexDWord(Const buf;len:SizeInt;b:DWord):SizeInt;
  154. type
  155. dwordarray = array [0..high(sizeint) div 4-1] of dword;
  156. var
  157. I : longint;
  158. begin
  159. I:=0;
  160. if (len < 0) then
  161. len := high(longint);
  162. while (I<Len) and (dwordarray(buf)[I]<>b) do
  163. inc(I);
  164. if (i=Len) then
  165. i:=-1; {Can't use 0, since it is a possible value for index}
  166. IndexDWord:=I;
  167. end;
  168. {$endif not FPC_SYSTEM_HAS_INDEXDWORD}
  169. {$ifndef FPC_SYSTEM_HAS_COMPARECHAR}
  170. function CompareChar(Const buf1,buf2;len:SizeInt):SizeInt;
  171. begin
  172. CompareChar:=CompareByte(buf1,buf2,len);
  173. end;
  174. {$endif not FPC_SYSTEM_HAS_COMPARECHAR}
  175. {$ifndef FPC_SYSTEM_HAS_COMPAREBYTE}
  176. function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt;
  177. type
  178. bytearray = array [0..high(sizeint)-1] of byte;
  179. var
  180. I : longint;
  181. begin
  182. I:=0;
  183. if (Len<>0) and (@Buf1<>@Buf2) then
  184. begin
  185. while (bytearray(Buf1)[I]=bytearray(Buf2)[I]) and (I<Len) do
  186. inc(I);
  187. if I=Len then {No difference}
  188. I:=0
  189. else
  190. begin
  191. I:=bytearray(Buf1)[I]-bytearray(Buf2)[I];
  192. if I>0 then
  193. I:=1
  194. else
  195. if I<0 then
  196. I:=-1;
  197. end;
  198. end;
  199. CompareByte:=I;
  200. end;
  201. {$endif not FPC_SYSTEM_HAS_COMPAREBYTE}
  202. {$ifndef FPC_SYSTEM_HAS_COMPAREWORD}
  203. function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt;
  204. type
  205. wordarray = array [0..high(sizeint) div 2-1] of word;
  206. var
  207. I : longint;
  208. begin
  209. I:=0;
  210. if (Len<>0) and (@Buf1<>@Buf2) then
  211. begin
  212. while (wordarray(Buf1)[I]=wordarray(Buf2)[I]) and (I<Len) do
  213. inc(I);
  214. if I=Len then {No difference}
  215. I:=0
  216. else
  217. begin
  218. I:=wordarray(Buf1)[I]-wordarray(Buf2)[I];
  219. if I>0 then
  220. I:=1
  221. else
  222. if I<0 then
  223. I:=-1;
  224. end;
  225. end;
  226. CompareWord:=I;
  227. end;
  228. {$endif not FPC_SYSTEM_HAS_COMPAREWORD}
  229. {$ifndef FPC_SYSTEM_HAS_COMPAREDWORD}
  230. function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt;
  231. type
  232. longintarray = array [0..high(sizeint) div 4-1] of longint;
  233. var
  234. I : longint;
  235. begin
  236. I:=0;
  237. if (Len<>0) and (@Buf1<>@Buf2) then
  238. begin
  239. while (longintarray(Buf1)[I]=longintarray(Buf2)[I]) and (I<Len) do
  240. inc(I);
  241. if I=Len then {No difference}
  242. I:=0
  243. else
  244. begin
  245. I:=longintarray(Buf1)[I]-longintarray(Buf2)[I];
  246. if I>0 then
  247. I:=1
  248. else
  249. if I<0 then
  250. I:=-1;
  251. end;
  252. end;
  253. CompareDWord:=I;
  254. end;
  255. {$endif ndef FPC_SYSTEM_HAS_COMPAREDWORD}
  256. {$ifndef FPC_SYSTEM_HAS_MOVECHAR0}
  257. procedure MoveChar0(Const buf1;var buf2;len:SizeInt);
  258. var
  259. I : longint;
  260. begin
  261. if Len = 0 then exit;
  262. I:=IndexByte(Buf1,Len,0);
  263. if I<>-1 then
  264. Move(Buf1,Buf2,I)
  265. else
  266. Move(Buf1,Buf2,len);
  267. end;
  268. {$endif ndef FPC_SYSTEM_HAS_MOVECHAR0}
  269. {$ifndef FPC_SYSTEM_HAS_INDEXCHAR0}
  270. function IndexChar0(Const buf;len:SizeInt;b:Char):SizeInt;
  271. var
  272. I : longint;
  273. begin
  274. if Len<>0 then
  275. begin
  276. I:=IndexByte(Buf,Len,0);
  277. If (I=-1) then
  278. I:=Len;
  279. IndexChar0:=IndexByte(Buf,I,byte(b));
  280. end
  281. else
  282. IndexChar0:=0;
  283. end;
  284. {$endif ndef FPC_SYSTEM_HAS_INDEXCHAR0}
  285. {$ifndef FPC_SYSTEM_HAS_COMPARECHAR0}
  286. function CompareChar0(Const buf1,buf2;len:SizeInt):SizeInt;
  287. type
  288. bytearray = array [0..high(sizeint)-1] of byte;
  289. var
  290. i : longint;
  291. begin
  292. I:=0;
  293. if (Len<>0) and (@Buf1<>@Buf2) then
  294. begin
  295. while (I<Len) And
  296. ((Pbyte(@Buf1)[i]<>0) and (PByte(@buf2)[i]<>0)) and
  297. (pbyte(@Buf1)[I]=pbyte(@Buf2)[I]) do
  298. inc(I);
  299. if (I=Len) or
  300. (PByte(@Buf1)[i]=0) or
  301. (PByte(@buf2)[I]=0) then {No difference or 0 reached }
  302. I:=0
  303. else
  304. begin
  305. I:=bytearray(Buf1)[I]-bytearray(Buf2)[I];
  306. if I>0 then
  307. I:=1
  308. else
  309. if I<0 then
  310. I:=-1;
  311. end;
  312. end;
  313. CompareChar0:=I;
  314. end;
  315. {$endif not FPC_SYSTEM_HAS_COMPARECHAR0}
  316. {****************************************************************************
  317. Object Helpers
  318. ****************************************************************************}
  319. {$ifndef FPC_SYSTEM_HAS_FPC_HELP_CONSTRUCTOR}
  320. { Note: _vmt will be reset to -1 when memory is allocated,
  321. this is needed for fpc_help_fail }
  322. function fpc_help_constructor(_self:pointer;var _vmt:pointer;_vmt_pos:cardinal):pointer;[public,alias:'FPC_HELP_CONSTRUCTOR'];compilerproc;
  323. type
  324. ppointer = ^pointer;
  325. pvmt = ^tvmt;
  326. tvmt=packed record
  327. size,msize:ptrint;
  328. parent:pointer;
  329. end;
  330. var
  331. vmtcopy : pointer;
  332. begin
  333. { Inherited call? }
  334. if _vmt=nil then
  335. begin
  336. fpc_help_constructor:=_self;
  337. exit;
  338. end;
  339. vmtcopy:=_vmt;
  340. if (_self=nil) and
  341. (pvmt(_vmt)^.size>0) then
  342. begin
  343. getmem(_self,pvmt(_vmt)^.size);
  344. { reset vmt needed for fail }
  345. _vmt:=pointer(-1);
  346. end;
  347. if _self<>nil then
  348. begin
  349. fillchar(_self^,pvmt(vmtcopy)^.size,#0);
  350. ppointer(_self+_vmt_pos)^:=vmtcopy;
  351. end;
  352. fpc_help_constructor:=_self;
  353. end;
  354. {$endif FPC_SYSTEM_HAS_FPC_HELP_CONSTRUCTOR}
  355. {$ifndef FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  356. { Note: _self will not be reset, the compiler has to generate the reset }
  357. procedure fpc_help_destructor(_self,_vmt:pointer;vmt_pos:cardinal);[public,alias:'FPC_HELP_DESTRUCTOR']; compilerproc;
  358. type
  359. ppointer = ^pointer;
  360. pvmt = ^tvmt;
  361. tvmt = packed record
  362. size,msize : ptrint;
  363. parent : pointer;
  364. end;
  365. begin
  366. { already released? }
  367. if (_self=nil) or
  368. (_vmt=nil) or
  369. (ppointer(_self+vmt_pos)^=nil) then
  370. exit;
  371. if (pvmt(ppointer(_self+vmt_pos)^)^.size=0) or
  372. (pvmt(ppointer(_self+vmt_pos)^)^.size+pvmt(ppointer(_self+vmt_pos)^)^.msize<>0) then
  373. RunError(210);
  374. { reset vmt to nil for protection }
  375. ppointer(_self+vmt_pos)^:=nil;
  376. freemem(_self);
  377. end;
  378. {$endif FPC_SYSTEM_HAS_FPC_HELP_DESTRUCTOR}
  379. {$ifndef FPC_SYSTEM_HAS_FPC_HELP_FAIL}
  380. { Note: _self will not be reset, the compiler has to generate the reset }
  381. procedure fpc_help_fail(_self:pointer;var _vmt:pointer;vmt_pos:cardinal);[public,alias:'FPC_HELP_FAIL'];compilerproc;
  382. type
  383. ppointer = ^pointer;
  384. pvmt = ^tvmt;
  385. tvmt = packed record
  386. size,msize : ptrint;
  387. parent : pointer;
  388. end;
  389. begin
  390. if (_self=nil) or (_vmt=nil) then
  391. exit;
  392. { vmt=-1 when memory was allocated }
  393. if ptrint(_vmt)=-1 then
  394. begin
  395. if (_self=nil) or (ppointer(_self+vmt_pos)^=nil) then
  396. HandleError(210)
  397. else
  398. begin
  399. ppointer(_self+vmt_pos)^:=nil;
  400. freemem(_self);
  401. { reset _vmt to nil so it will not be freed a
  402. second time }
  403. _vmt:=nil;
  404. end;
  405. end
  406. else
  407. ppointer(_self+vmt_pos)^:=nil;
  408. end;
  409. {$endif FPC_SYSTEM_HAS_FPC_HELP_FAIL}
  410. {$ifndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  411. procedure fpc_check_object(_vmt : pointer); [public,alias:'FPC_CHECK_OBJECT']; compilerproc;
  412. type
  413. pvmt = ^tvmt;
  414. tvmt = packed record
  415. size,msize : ptrint;
  416. parent : pointer;
  417. end;
  418. begin
  419. if (_vmt=nil) or
  420. (pvmt(_vmt)^.size=0) or
  421. (pvmt(_vmt)^.size+pvmt(_vmt)^.msize<>0) then
  422. RunError(210);
  423. end;
  424. {$endif ndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  425. {$ifndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  426. { checks for a correct vmt pointer }
  427. { deeper check to see if the current object is }
  428. { really related to the true }
  429. procedure fpc_check_object_ext(vmt, expvmt : pointer); [public,alias:'FPC_CHECK_OBJECT_EXT']; compilerproc;
  430. type
  431. pvmt = ^tvmt;
  432. tvmt = packed record
  433. size,msize : ptrint;
  434. parent : pointer;
  435. end;
  436. begin
  437. if (vmt=nil) or
  438. (pvmt(vmt)^.size=0) or
  439. (pvmt(vmt)^.size+pvmt(vmt)^.msize<>0) then
  440. RunError(210);
  441. while assigned(vmt) do
  442. if vmt=expvmt then
  443. exit
  444. else
  445. vmt:=pvmt(vmt)^.parent;
  446. RunError(219);
  447. end;
  448. {$endif not FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  449. {****************************************************************************
  450. String
  451. ****************************************************************************}
  452. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  453. function fpc_shortstr_to_shortstr(len:longint;const sstr:shortstring): shortstring;[public,alias:'FPC_SHORTSTR_TO_SHORTSTR']; compilerproc;
  454. var
  455. slen : byte;
  456. begin
  457. slen:=length(sstr);
  458. if slen<len then
  459. len:=slen;
  460. move(sstr[0],result[0],len+1);
  461. if slen>len then
  462. result[0]:=chr(len);
  463. end;
  464. procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN']; {$ifdef HAS_COMPILER_PROC} compilerproc; {$endif}
  465. var
  466. slen : byte;
  467. type
  468. pstring = ^string;
  469. begin
  470. slen:=length(pstring(sstr)^);
  471. if slen<len then
  472. len:=slen;
  473. move(sstr^,dstr^,len+1);
  474. if slen>len then
  475. pchar(dstr)^:=chr(len);
  476. end;
  477. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  478. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  479. function fpc_shortstr_concat(const s1,s2:shortstring): shortstring;[public,alias:'FPC_SHORTSTR_CONCAT']; compilerproc;
  480. var
  481. s1l, s2l : byte;
  482. begin
  483. s1l:=length(s1);
  484. s2l:=length(s2);
  485. if s1l+s2l>255 then
  486. s2l:=255-s1l;
  487. move(s1[1],fpc_shortstr_concat[1],s1l);
  488. move(s2[1],fpc_shortstr_concat[s1l+1],s2l);
  489. fpc_shortstr_concat[0]:=chr(s1l+s2l);
  490. end;
  491. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  492. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  493. procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring);compilerproc;
  494. [public,alias:'FPC_SHORTSTR_APPEND_SHORTSTR'];
  495. var
  496. s1l, s2l : byte;
  497. begin
  498. s1l:=length(s1);
  499. s2l:=length(s2);
  500. if s1l+s2l>high(s1) then
  501. s2l:=high(s1)-s1l;
  502. move(s2[1],s1[s1l+1],s2l);
  503. s1[0]:=chr(s1l+s2l);
  504. end;
  505. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  506. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  507. function fpc_shortstr_compare(const left,right:shortstring) : longint;[public,alias:'FPC_SHORTSTR_COMPARE']; compilerproc;
  508. var
  509. s1,s2,max,i : byte;
  510. d : longint;
  511. begin
  512. s1:=length(left);
  513. s2:=length(right);
  514. if s1<s2 then
  515. max:=s1
  516. else
  517. max:=s2;
  518. for i:=1 to max do
  519. begin
  520. d:=byte(left[i])-byte(right[i]);
  521. if d>0 then
  522. exit(1)
  523. else if d<0 then
  524. exit(-1);
  525. end;
  526. if s1>s2 then
  527. exit(1)
  528. else if s1<s2 then
  529. exit(-1)
  530. else
  531. exit(0);
  532. end;
  533. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  534. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  535. function fpc_pchar_to_shortstr(p:pchar):shortstring;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; compilerproc;
  536. var
  537. l : longint;
  538. s: shortstring;
  539. begin
  540. if p=nil then
  541. l:=0
  542. else
  543. l:=strlen(p);
  544. if l>255 then
  545. l:=255;
  546. if l>0 then
  547. move(p^,s[1],l);
  548. s[0]:=chr(l);
  549. fpc_pchar_to_shortstr := s;
  550. end;
  551. {$endif ndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  552. {$ifndef FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  553. function fpc_chararray_to_shortstr(const arr: array of char; zerobased: boolean = true):shortstring;[public,alias:'FPC_CHARARRAY_TO_SHORTSTR']; compilerproc;
  554. var
  555. l: longint;
  556. index: longint;
  557. len: byte;
  558. begin
  559. l := high(arr)+1;
  560. if l>=256 then
  561. l:=255
  562. else if l<0 then
  563. l:=0;
  564. if (zerobased) then
  565. begin
  566. index:=IndexByte(arr[0],l,0);
  567. if (index < 0) then
  568. len := l
  569. else
  570. len := index;
  571. end
  572. else
  573. len := l;
  574. move(arr[0],fpc_chararray_to_shortstr[1],len);
  575. fpc_chararray_to_shortstr[0]:=chr(len);
  576. end;
  577. {$endif ndef FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  578. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_TO_CHARARRAY}
  579. { inside the compiler, the resulttype is modified to that of the actual }
  580. { chararray we're converting to (JM) }
  581. function fpc_shortstr_to_chararray(arraysize: longint; const src: ShortString): fpc_big_chararray;[public,alias: 'FPC_SHORTSTR_TO_CHARARRAY']; compilerproc;
  582. var
  583. len: longint;
  584. begin
  585. len := length(src);
  586. if len > arraysize then
  587. len := arraysize;
  588. { make sure we don't access char 1 if length is 0 (JM) }
  589. if len > 0 then
  590. move(src[1],fpc_shortstr_to_chararray[0],len);
  591. fillchar(fpc_shortstr_to_chararray[len],arraysize-len,0);
  592. end;
  593. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_TO_CHARARRAY}
  594. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  595. function fpc_pchar_length(p:pchar):longint;[public,alias:'FPC_PCHAR_LENGTH']; compilerproc;
  596. var i : longint;
  597. begin
  598. i:=0;
  599. while p[i]<>#0 do inc(i);
  600. exit(i);
  601. end;
  602. {$endif ndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  603. {$ifndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  604. function fpc_pwidechar_length(p:pwidechar):longint;[public,alias:'FPC_PWIDECHAR_LENGTH']; compilerproc;
  605. var i : longint;
  606. begin
  607. i:=0;
  608. while p[i]<>#0 do inc(i);
  609. exit(i);
  610. end;
  611. {$endif ndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  612. {****************************************************************************
  613. Caller/StackFrame Helpers
  614. ****************************************************************************}
  615. {$ifndef FPC_SYSTEM_HAS_GET_FRAME}
  616. {_$error Get_frame must be defined for each processor }
  617. {$endif ndef FPC_SYSTEM_HAS_GET_FRAME}
  618. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  619. {_$error Get_caller_addr must be defined for each processor }
  620. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  621. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  622. {_$error Get_caller_frame must be defined for each processor }
  623. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  624. {****************************************************************************
  625. Math
  626. ****************************************************************************}
  627. {****************************************************************************
  628. Software longint/dword division
  629. ****************************************************************************}
  630. {$ifdef FPC_INCLUDE_SOFTWARE_MOD_DIV}
  631. function count_leading_zeros_32bit(l : longint) : longint;
  632. var
  633. i : longint;
  634. begin
  635. for i:=0 to 31 do
  636. begin
  637. if (l and (longint($80000000) shr i))<>0 then
  638. begin
  639. result:=i;
  640. exit;
  641. end;
  642. end;
  643. result:=i;
  644. end;
  645. {$ifndef FPC_SYSTEM_HAS_DIV_DWORD}
  646. function fpc_div_dword(n,z : dword) : dword; [public,alias: 'FPC_DIV_DWORD']; compilerproc;
  647. var
  648. shift,lzz,lzn : longint;
  649. begin
  650. result:=0;
  651. if n=0 then
  652. HandleErrorFrame(200,get_frame);
  653. lzz:=count_leading_zeros_32bit(z);
  654. lzn:=count_leading_zeros_32bit(n);
  655. { if the denominator contains less zeros
  656. then the numerator
  657. the d is greater than the n }
  658. if lzn<lzz then
  659. exit;
  660. shift:=lzn-lzz;
  661. n:=n shl shift;
  662. repeat
  663. if z>=n then
  664. begin
  665. z:=z-n;
  666. result:=result+dword(1 shl shift);
  667. end;
  668. dec(shift);
  669. n:=n shr 1;
  670. until shift<0;
  671. end;
  672. {$endif FPC_SYSTEM_HAS_DIV_DWORD}
  673. {$ifndef FPC_SYSTEM_HAS_MOD_DWORD}
  674. function fpc_mod_dword(n,z : dword) : dword; [public,alias: 'FPC_MOD_DWORD']; compilerproc;
  675. var
  676. shift,lzz,lzn : longint;
  677. begin
  678. result:=0;
  679. if n=0 then
  680. HandleErrorFrame(200,get_frame);
  681. lzz:=count_leading_zeros_32bit(z);
  682. lzn:=count_leading_zeros_32bit(n);
  683. { if the denominator contains less zeros
  684. then the numerator
  685. the d is greater than the n }
  686. if lzn<lzz then
  687. begin
  688. result:=z;
  689. exit;
  690. end;
  691. shift:=lzn-lzz;
  692. n:=n shl shift;
  693. repeat
  694. if z>=n then
  695. z:=z-n;
  696. dec(shift);
  697. n:=n shr 1;
  698. until shift<0;
  699. result:=z;
  700. end;
  701. {$endif FPC_SYSTEM_HAS_MOD_DWORD}
  702. {$ifndef FPC_SYSTEM_HAS_DIV_LONGINT}
  703. function fpc_div_longint(n,z : longint) : longint; [public,alias: 'FPC_DIV_LONGINT']; compilerproc;
  704. var
  705. sign : boolean;
  706. d1,d2 : dword;
  707. begin
  708. if n=0 then
  709. HandleErrorFrame(200,get_frame);
  710. sign:=false;
  711. if z<0 then
  712. begin
  713. sign:=not(sign);
  714. d1:=dword(-z);
  715. end
  716. else
  717. d1:=z;
  718. if n<0 then
  719. begin
  720. sign:=not(sign);
  721. d2:=dword(-n);
  722. end
  723. else
  724. d2:=n;
  725. { the div is coded by the compiler as call to divdword }
  726. if sign then
  727. result:=-(d1 div d2)
  728. else
  729. result:=d1 div d2;
  730. end;
  731. {$endif FPC_SYSTEM_HAS_DIV_LONGINT}
  732. {$ifndef FPC_SYSTEM_HAS_MOD_LONGINT}
  733. function fpc_mod_longint(n,z : longint) : longint; [public,alias: 'FPC_MOD_LONGINT']; compilerproc;
  734. var
  735. signed : boolean;
  736. r,nq,zq : dword;
  737. begin
  738. if n=0 then
  739. HandleErrorFrame(200,get_frame);
  740. nq:=abs(n);
  741. if z<0 then
  742. begin
  743. zq:=dword(-z);
  744. signed:=true;
  745. end
  746. else
  747. begin
  748. zq:=z;
  749. signed:=false;
  750. end;
  751. r:=zq mod nq;
  752. if signed then
  753. result:=-longint(r)
  754. else
  755. result:=r;
  756. end;
  757. {$endif FPC_SYSTEM_HAS_MOD_LONGINT}
  758. {$endif FPC_INCLUDE_SOFTWARE_MOD_DIV}
  759. {****************************************************************************}
  760. {$ifndef FPC_SYSTEM_HAS_ABS_LONGINT}
  761. function abs(l:longint):longint;{$ifdef SYSTEMINLINE}inline;{$endif}
  762. begin
  763. if l<0 then
  764. abs:=-l
  765. else
  766. abs:=l;
  767. end;
  768. {$endif not FPC_SYSTEM_HAS_ABS_LONGINT}
  769. {$ifndef FPC_SYSTEM_HAS_ODD_LONGINT}
  770. function odd(l:longint):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  771. begin
  772. odd:=boolean(l and 1);
  773. end;
  774. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGINT}
  775. {$ifndef FPC_SYSTEM_HAS_ODD_LONGWORD}
  776. function odd(l:longword):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  777. begin
  778. odd:=boolean(l and 1);
  779. end;
  780. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGWORD}
  781. {$ifndef FPC_SYSTEM_HAS_ODD_INT64}
  782. function odd(l:int64):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  783. begin
  784. odd:=boolean(longint(l) and 1);
  785. end;
  786. {$endif ndef FPC_SYSTEM_HAS_ODD_INT64}
  787. {$ifndef FPC_SYSTEM_HAS_ODD_QWORD}
  788. function odd(l:qword):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  789. begin
  790. odd:=boolean(longint(l) and 1);
  791. end;
  792. {$endif ndef FPC_SYSTEM_HAS_ODD_QWORD}
  793. {$ifndef FPC_SYSTEM_HAS_SQR_LONGINT}
  794. function sqr(l:longint):longint;{$ifdef SYSTEMINLINE}inline;{$endif}
  795. begin
  796. sqr:=l*l;
  797. end;
  798. {$endif ndef FPC_SYSTEM_HAS_SQR_LONGINT}
  799. {$ifndef FPC_SYSTEM_HAS_ABS_INT64}
  800. function abs(l: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  801. begin
  802. if l < 0 then
  803. abs := -l
  804. else
  805. abs := l;
  806. end;
  807. {$endif ndef FPC_SYSTEM_HAS_ABS_INT64}
  808. {$ifndef FPC_SYSTEM_HAS_SQR_INT64}
  809. function sqr(l: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  810. begin
  811. sqr := l*l;
  812. end;
  813. {$endif ndef FPC_SYSTEM_HAS_SQR_INT64}
  814. {$ifndef FPC_SYSTEM_HAS_SQR_QWORD}
  815. function sqr(l: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  816. begin
  817. sqr := l*l;
  818. end;
  819. {$endif ndef FPC_SYSTEM_HAS_SQR_INT64}
  820. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  821. function declocked(var l:longint):boolean;
  822. begin
  823. Dec(l);
  824. declocked:=(l=0);
  825. end;
  826. {$endif FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  827. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_INT64}
  828. function declocked(var l:int64):boolean;
  829. begin
  830. Dec(l);
  831. declocked:=(l=0);
  832. end;
  833. {$endif FPC_SYSTEM_HAS_DECLOCKED_INT64}
  834. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  835. procedure inclocked(var l:longint);
  836. begin
  837. Inc(l);
  838. end;
  839. {$endif FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  840. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_INT64}
  841. procedure inclocked(var l:int64);
  842. begin
  843. Inc(l);
  844. end;
  845. {$endif FPC_SYSTEM_HAS_INCLOCKED_INT64}
  846. {$ifndef FPC_SYSTEM_HAS_SPTR}
  847. {_$error Sptr must be defined for each processor }
  848. {$endif ndef FPC_SYSTEM_HAS_SPTR}
  849. function align(addr : PtrInt;alignment : PtrInt) : PtrInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  850. begin
  851. if addr mod alignment<>0 then
  852. result:=addr+(alignment-(addr mod alignment))
  853. else
  854. result:=addr;
  855. end;
  856. function align(addr : Pointer;alignment : PtrInt) : Pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
  857. begin
  858. if PtrInt(addr) mod alignment<>0 then
  859. result:=pointer(addr+(alignment-(PtrInt(addr) mod alignment)))
  860. else
  861. result:=addr;
  862. end;
  863. {****************************************************************************
  864. Str()
  865. ****************************************************************************}
  866. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  867. procedure int_str(l:longint;out s:string);
  868. var m:cardinal;
  869. p:byte;
  870. begin
  871. s[1]:='-'; {Will be overwritten if positive.}
  872. p:=byte(l<0); {Number of characters to start with.}
  873. {Count number of characters.}
  874. m:=abs(l);
  875. repeat
  876. inc(p);
  877. l:=l div 10;
  878. until l=0;
  879. {Generate string.}
  880. s[0]:=char(p);
  881. repeat
  882. s[p]:=char(m mod 10+byte('0'));
  883. m:=m div 10;
  884. dec(p);
  885. until m=0;
  886. end;
  887. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  888. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  889. procedure int_str(l:longword;out s:string);
  890. var m:longword;
  891. p:byte;
  892. begin
  893. p:=0;
  894. {Count number of characters.}
  895. m:=l;
  896. repeat
  897. inc(p);
  898. m:=m div 10;
  899. until m=0;
  900. {Generate string.}
  901. s[0]:=char(p);
  902. repeat
  903. s[p]:=char((l mod 10)+byte('0'));
  904. l:=l div 10;
  905. dec(p);
  906. until l=0;
  907. end;
  908. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  909. {$ifndef FPC_SYSTEM_HAS_INT_STR_INT64}
  910. procedure int_str(l:int64;out s:string);
  911. var m:qword;
  912. p:byte;
  913. begin
  914. s[1]:='-'; {Will be overwritten if positive.}
  915. p:=byte(l<0); {Number of characters to start with.}
  916. {Count number of characters.}
  917. m:=abs(l);
  918. repeat
  919. inc(p);
  920. l:=l div 10;
  921. until l=0;
  922. {Generate string.}
  923. s[0]:=char(p);
  924. repeat
  925. s[p]:=char(m mod 10+byte('0'));
  926. m:=m div 10;
  927. dec(p);
  928. until m=0;
  929. end;
  930. {$endif ndef FPC_SYSTEM_HAS_INT_STR_INT64}
  931. {$ifndef FPC_SYSTEM_HAS_INT_STR_QWORD}
  932. procedure int_str(l:qword;out s:string);
  933. var m:qword;
  934. p:byte;
  935. begin
  936. p:=0;
  937. {Count number of characters.}
  938. m:=l;
  939. repeat
  940. inc(p);
  941. m:=m div 10;
  942. until m=0;
  943. {Generate string.}
  944. s[0]:=char(p);
  945. repeat
  946. s[p]:=char((l mod 10)+byte('0'));
  947. l:=l div 10;
  948. dec(p);
  949. until l=0;
  950. end;
  951. {$endif ndef FPC_SYSTEM_HAS_INT_STR_QWORD}
  952. {$ifndef FPC_SYSTEM_HAS_SYSRESETFPU}
  953. procedure SysResetFpu;{$ifdef SYSTEMINLINE}inline;{$endif}
  954. begin
  955. { nothing todo }
  956. end;
  957. {$endif FPC_SYSTEM_HAS_SYSRESETFPU}