generic.inc 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136
  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):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. index:=IndexByte(arr[0],l,0);
  565. if (index < 0) then
  566. len := l
  567. else
  568. len := index;
  569. move(arr[0],fpc_chararray_to_shortstr[1],len);
  570. fpc_chararray_to_shortstr[0]:=chr(len);
  571. end;
  572. {$endif ndef FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  573. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_TO_CHARARRAY}
  574. { inside the compiler, the resulttype is modified to that of the actual }
  575. { chararray we're converting to (JM) }
  576. function fpc_shortstr_to_chararray(arraysize: longint; const src: ShortString): fpc_big_chararray;[public,alias: 'FPC_SHORTSTR_TO_CHARARRAY']; compilerproc;
  577. var
  578. len: longint;
  579. begin
  580. len := length(src);
  581. if len > arraysize then
  582. len := arraysize;
  583. { make sure we don't access char 1 if length is 0 (JM) }
  584. if len > 0 then
  585. move(src[1],fpc_shortstr_to_chararray[0],len);
  586. fillchar(fpc_shortstr_to_chararray[len],arraysize-len,0);
  587. end;
  588. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_TO_CHARARRAY}
  589. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  590. function fpc_pchar_length(p:pchar):longint;[public,alias:'FPC_PCHAR_LENGTH']; compilerproc;
  591. var i : longint;
  592. begin
  593. i:=0;
  594. while p[i]<>#0 do inc(i);
  595. exit(i);
  596. end;
  597. {$endif ndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  598. {$ifndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  599. function fpc_pwidechar_length(p:pwidechar):longint;[public,alias:'FPC_PWIDECHAR_LENGTH']; compilerproc;
  600. var i : longint;
  601. begin
  602. i:=0;
  603. while p[i]<>#0 do inc(i);
  604. exit(i);
  605. end;
  606. {$endif ndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  607. {****************************************************************************
  608. Caller/StackFrame Helpers
  609. ****************************************************************************}
  610. {$ifndef FPC_SYSTEM_HAS_GET_FRAME}
  611. {_$error Get_frame must be defined for each processor }
  612. {$endif ndef FPC_SYSTEM_HAS_GET_FRAME}
  613. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  614. {_$error Get_caller_addr must be defined for each processor }
  615. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  616. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  617. {_$error Get_caller_frame must be defined for each processor }
  618. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  619. {****************************************************************************
  620. Math
  621. ****************************************************************************}
  622. {****************************************************************************
  623. Software longint/dword division
  624. ****************************************************************************}
  625. {$ifdef FPC_INCLUDE_SOFTWARE_MOD_DIV}
  626. function count_leading_zeros_32bit(l : longint) : longint;
  627. var
  628. i : longint;
  629. begin
  630. for i:=0 to 31 do
  631. begin
  632. if (l and (longint($80000000) shr i))<>0 then
  633. begin
  634. result:=i;
  635. exit;
  636. end;
  637. end;
  638. result:=i;
  639. end;
  640. {$ifndef FPC_SYSTEM_HAS_DIV_DWORD}
  641. function fpc_div_dword(n,z : dword) : dword; [public,alias: 'FPC_DIV_DWORD']; compilerproc;
  642. var
  643. shift,lzz,lzn : longint;
  644. begin
  645. result:=0;
  646. if n=0 then
  647. HandleErrorFrame(200,get_frame);
  648. lzz:=count_leading_zeros_32bit(z);
  649. lzn:=count_leading_zeros_32bit(n);
  650. { if the denominator contains less zeros
  651. then the numerator
  652. the d is greater than the n }
  653. if lzn<lzz then
  654. exit;
  655. shift:=lzn-lzz;
  656. n:=n shl shift;
  657. repeat
  658. if z>=n then
  659. begin
  660. z:=z-n;
  661. result:=result+dword(1 shl shift);
  662. end;
  663. dec(shift);
  664. n:=n shr 1;
  665. until shift<0;
  666. end;
  667. {$endif FPC_SYSTEM_HAS_DIV_DWORD}
  668. {$ifndef FPC_SYSTEM_HAS_MOD_DWORD}
  669. function fpc_mod_dword(n,z : dword) : dword; [public,alias: 'FPC_MOD_DWORD']; compilerproc;
  670. var
  671. shift,lzz,lzn : longint;
  672. begin
  673. result:=0;
  674. if n=0 then
  675. HandleErrorFrame(200,get_frame);
  676. lzz:=count_leading_zeros_32bit(z);
  677. lzn:=count_leading_zeros_32bit(n);
  678. { if the denominator contains less zeros
  679. then the numerator
  680. the d is greater than the n }
  681. if lzn<lzz then
  682. begin
  683. result:=z;
  684. exit;
  685. end;
  686. shift:=lzn-lzz;
  687. n:=n shl shift;
  688. repeat
  689. if z>=n then
  690. z:=z-n;
  691. dec(shift);
  692. n:=n shr 1;
  693. until shift<0;
  694. result:=z;
  695. end;
  696. {$endif FPC_SYSTEM_HAS_MOD_DWORD}
  697. {$ifndef FPC_SYSTEM_HAS_DIV_LONGINT}
  698. function fpc_div_longint(n,z : longint) : longint; [public,alias: 'FPC_DIV_LONGINT']; compilerproc;
  699. var
  700. sign : boolean;
  701. d1,d2 : dword;
  702. begin
  703. if n=0 then
  704. HandleErrorFrame(200,get_frame);
  705. sign:=false;
  706. if z<0 then
  707. begin
  708. sign:=not(sign);
  709. d1:=dword(-z);
  710. end
  711. else
  712. d1:=z;
  713. if n<0 then
  714. begin
  715. sign:=not(sign);
  716. d2:=dword(-n);
  717. end
  718. else
  719. d2:=n;
  720. { the div is coded by the compiler as call to divdword }
  721. if sign then
  722. result:=-(d1 div d2)
  723. else
  724. result:=d1 div d2;
  725. end;
  726. {$endif FPC_SYSTEM_HAS_DIV_LONGINT}
  727. {$ifndef FPC_SYSTEM_HAS_MOD_LONGINT}
  728. function fpc_mod_longint(n,z : longint) : longint; [public,alias: 'FPC_MOD_LONGINT']; compilerproc;
  729. var
  730. signed : boolean;
  731. r,nq,zq : dword;
  732. begin
  733. if n=0 then
  734. HandleErrorFrame(200,get_frame);
  735. nq:=abs(n);
  736. if z<0 then
  737. begin
  738. zq:=dword(-z);
  739. signed:=true;
  740. end
  741. else
  742. begin
  743. zq:=z;
  744. signed:=false;
  745. end;
  746. r:=zq mod nq;
  747. if signed then
  748. result:=-longint(r)
  749. else
  750. result:=r;
  751. end;
  752. {$endif FPC_SYSTEM_HAS_MOD_LONGINT}
  753. {$endif FPC_INCLUDE_SOFTWARE_MOD_DIV}
  754. {****************************************************************************}
  755. {$ifndef FPC_SYSTEM_HAS_ABS_LONGINT}
  756. function abs(l:longint):longint;{$ifdef SYSTEMINLINE}inline;{$endif}
  757. begin
  758. if l<0 then
  759. abs:=-l
  760. else
  761. abs:=l;
  762. end;
  763. {$endif not FPC_SYSTEM_HAS_ABS_LONGINT}
  764. {$ifndef FPC_SYSTEM_HAS_ODD_LONGINT}
  765. function odd(l:longint):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  766. begin
  767. odd:=boolean(l and 1);
  768. end;
  769. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGINT}
  770. {$ifndef FPC_SYSTEM_HAS_ODD_LONGWORD}
  771. function odd(l:longword):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  772. begin
  773. odd:=boolean(l and 1);
  774. end;
  775. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGWORD}
  776. {$ifndef FPC_SYSTEM_HAS_ODD_INT64}
  777. function odd(l:int64):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  778. begin
  779. odd:=boolean(longint(l) and 1);
  780. end;
  781. {$endif ndef FPC_SYSTEM_HAS_ODD_INT64}
  782. {$ifndef FPC_SYSTEM_HAS_ODD_QWORD}
  783. function odd(l:qword):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}
  784. begin
  785. odd:=boolean(longint(l) and 1);
  786. end;
  787. {$endif ndef FPC_SYSTEM_HAS_ODD_QWORD}
  788. {$ifndef FPC_SYSTEM_HAS_SQR_LONGINT}
  789. function sqr(l:longint):longint;{$ifdef SYSTEMINLINE}inline;{$endif}
  790. begin
  791. sqr:=l*l;
  792. end;
  793. {$endif ndef FPC_SYSTEM_HAS_SQR_LONGINT}
  794. {$ifndef FPC_SYSTEM_HAS_ABS_INT64}
  795. function abs(l: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  796. begin
  797. if l < 0 then
  798. abs := -l
  799. else
  800. abs := l;
  801. end;
  802. {$endif ndef FPC_SYSTEM_HAS_ABS_INT64}
  803. {$ifndef FPC_SYSTEM_HAS_SQR_INT64}
  804. function sqr(l: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}
  805. begin
  806. sqr := l*l;
  807. end;
  808. {$endif ndef FPC_SYSTEM_HAS_SQR_INT64}
  809. {$ifndef FPC_SYSTEM_HAS_SQR_QWORD}
  810. function sqr(l: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}
  811. begin
  812. sqr := l*l;
  813. end;
  814. {$endif ndef FPC_SYSTEM_HAS_SQR_INT64}
  815. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  816. function declocked(var l:longint):boolean;
  817. begin
  818. Dec(l);
  819. declocked:=(l=0);
  820. end;
  821. {$endif FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  822. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_INT64}
  823. function declocked(var l:int64):boolean;
  824. begin
  825. Dec(l);
  826. declocked:=(l=0);
  827. end;
  828. {$endif FPC_SYSTEM_HAS_DECLOCKED_INT64}
  829. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  830. procedure inclocked(var l:longint);
  831. begin
  832. Inc(l);
  833. end;
  834. {$endif FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  835. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_INT64}
  836. procedure inclocked(var l:int64);
  837. begin
  838. Inc(l);
  839. end;
  840. {$endif FPC_SYSTEM_HAS_INCLOCKED_INT64}
  841. {$ifndef FPC_SYSTEM_HAS_SPTR}
  842. {_$error Sptr must be defined for each processor }
  843. {$endif ndef FPC_SYSTEM_HAS_SPTR}
  844. function align(addr : PtrInt;alignment : PtrInt) : PtrInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  845. begin
  846. if addr mod alignment<>0 then
  847. result:=addr+(alignment-(addr mod alignment))
  848. else
  849. result:=addr;
  850. end;
  851. function align(addr : Pointer;alignment : PtrInt) : Pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
  852. begin
  853. if PtrInt(addr) mod alignment<>0 then
  854. result:=pointer(addr+(alignment-(PtrInt(addr) mod alignment)))
  855. else
  856. result:=addr;
  857. end;
  858. {****************************************************************************
  859. Str()
  860. ****************************************************************************}
  861. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  862. procedure int_str(l : longint;out s : string);
  863. var
  864. value: longint;
  865. negative: boolean;
  866. begin
  867. negative := false;
  868. s:='';
  869. { Workaround: }
  870. if l=longint($80000000) then
  871. begin
  872. s:='-2147483648';
  873. exit;
  874. end;
  875. { handle case where l = 0 }
  876. if l = 0 then
  877. begin
  878. s:='0';
  879. exit;
  880. end;
  881. If l < 0 then
  882. begin
  883. negative := true;
  884. value:=abs(l);
  885. end
  886. else
  887. value:=l;
  888. { handle non-zero case }
  889. while value>0 do
  890. begin
  891. s:=char((value mod 10)+ord('0'))+s;
  892. value := value div 10;
  893. end;
  894. if negative then
  895. s := '-' + s;
  896. end;
  897. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  898. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  899. procedure int_str(l : longword;out s : string);
  900. begin
  901. s:='';
  902. if l = 0 then
  903. begin
  904. s := '0';
  905. exit;
  906. end;
  907. while l>0 do
  908. begin
  909. s:=char(ord('0')+(l mod 10))+s;
  910. l:=l div 10;
  911. end;
  912. end;
  913. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  914. {$ifndef FPC_SYSTEM_HAS_INT_STR_INT64}
  915. procedure int_str(l : int64;out s : string);
  916. var
  917. value: int64;
  918. negative: boolean;
  919. begin
  920. negative := false;
  921. s:='';
  922. { Workaround: }
  923. if l=int64($8000000000000000) then
  924. begin
  925. s:='-9223372036854775808';
  926. exit;
  927. end;
  928. { handle case where l = 0 }
  929. if l = 0 then
  930. begin
  931. s:='0';
  932. exit;
  933. end;
  934. If l < 0 then
  935. begin
  936. negative := true;
  937. value:=abs(l);
  938. end
  939. else
  940. value:=l;
  941. { handle non-zero case }
  942. while value>0 do
  943. begin
  944. s:=char((value mod 10)+ord('0'))+s;
  945. value := value div 10;
  946. end;
  947. if negative then
  948. s := '-' + s;
  949. end;
  950. {$endif ndef FPC_SYSTEM_HAS_INT_STR_INT64}
  951. {$ifndef FPC_SYSTEM_HAS_INT_STR_QWORD}
  952. procedure int_str(l : qword;out s : string);
  953. begin
  954. s:='';
  955. if l = 0 then
  956. begin
  957. s := '0';
  958. exit;
  959. end;
  960. while l>0 do
  961. begin
  962. s:=char(ord('0')+(l mod 10))+s;
  963. l:=l div 10;
  964. end;
  965. end;
  966. {$endif ndef FPC_SYSTEM_HAS_INT_STR_QWORD}
  967. {$ifndef FPC_SYSTEM_HAS_SYSRESETFPU}
  968. procedure SysResetFpu;{$ifdef SYSTEMINLINE}inline;{$endif}
  969. begin
  970. { nothing todo }
  971. end;
  972. {$endif FPC_SYSTEM_HAS_SYSRESETFPU}