generic.inc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230
  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'];{$ifdef hascompilerproc}compilerproc;{$endif}
  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']; {$ifdef hascompilerproc} compilerproc; {$endif}
  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 NOCLASSHELPERS}
  411. {$ifndef FPC_SYSTEM_HAS_FPC_NEW_CLASS}
  412. function fpc_new_class(_self,_vmt:pointer):pointer;[public,alias:'FPC_NEW_CLASS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  413. begin
  414. { Inherited call? }
  415. if _vmt=nil then
  416. begin
  417. fpc_new_class:=_self;
  418. exit;
  419. end;
  420. fpc_new_class := tclass(_vmt).NewInstance
  421. end;
  422. {$endif FPC_SYSTEM_HAS_FPC_NEW_CLASS}
  423. {$ifndef FPC_SYSTEM_HAS_FPC_DISPOSE_CLASS}
  424. procedure fpc_dispose_class(_self: pointer; flag : longint);[public,alias:'FPC_DISPOSE_CLASS'];compilerproc;
  425. begin
  426. { inherited -> flag = 0 -> no destroy }
  427. { normal -> flag = 1 -> destroy }
  428. if (_self <> nil) and (flag = 1) then
  429. tobject(_self).FreeInstance;
  430. end;
  431. {$endif ndef FPC_SYSTEM_HAS_FPC_DISPOSE_CLASS}
  432. {$endif NOCLASSHELPERS}
  433. {$ifndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  434. procedure fpc_check_object(_vmt : pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[public,alias:'FPC_CHECK_OBJECT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  435. type
  436. pvmt = ^tvmt;
  437. tvmt = packed record
  438. size,msize : ptrint;
  439. parent : pointer;
  440. end;
  441. begin
  442. if (_vmt=nil) or
  443. (pvmt(_vmt)^.size=0) or
  444. (pvmt(_vmt)^.size+pvmt(_vmt)^.msize<>0) then
  445. RunError(210);
  446. end;
  447. {$endif ndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT}
  448. {$ifndef FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  449. { checks for a correct vmt pointer }
  450. { deeper check to see if the current object is }
  451. { really related to the true }
  452. procedure fpc_check_object_ext(vmt, expvmt : pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[public,alias:'FPC_CHECK_OBJECT_EXT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  453. type
  454. pvmt = ^tvmt;
  455. tvmt = packed record
  456. size,msize : ptrint;
  457. parent : pointer;
  458. end;
  459. begin
  460. if (vmt=nil) or
  461. (pvmt(vmt)^.size=0) or
  462. (pvmt(vmt)^.size+pvmt(vmt)^.msize<>0) then
  463. RunError(210);
  464. while assigned(vmt) do
  465. if vmt=expvmt then
  466. exit
  467. else
  468. vmt:=pvmt(vmt)^.parent;
  469. RunError(219);
  470. end;
  471. {$endif not FPC_SYSTEM_HAS_FPC_CHECK_OBJECT_EXT}
  472. {****************************************************************************
  473. String
  474. ****************************************************************************}
  475. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  476. function fpc_shortstr_to_shortstr(len:longint;const sstr:shortstring): shortstring;[public,alias:'FPC_SHORTSTR_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  477. var
  478. slen : byte;
  479. begin
  480. slen:=length(sstr);
  481. if slen<len then
  482. len:=slen;
  483. move(sstr[0],result[0],len+1);
  484. if slen>len then
  485. result[0]:=chr(len);
  486. end;
  487. {$ifdef interncopy}
  488. procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_ASSIGN']; {$ifdef HAS_COMPILER_PROC} compilerproc; {$endif}
  489. {$else}
  490. procedure fpc_shortstr_copy(len:longint;sstr,dstr:pointer);[public,alias:'FPC_SHORTSTR_COPY']; {$ifdef HAS_COMPILER_PROC} compilerproc; {$endif}
  491. {$endif}
  492. var
  493. slen : byte;
  494. type
  495. pstring = ^string;
  496. begin
  497. slen:=length(pstring(sstr)^);
  498. if slen<len then
  499. len:=slen;
  500. move(sstr^,dstr^,len+1);
  501. if slen>len then
  502. pchar(dstr)^:=chr(len);
  503. end;
  504. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
  505. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  506. function fpc_shortstr_concat(const s1,s2:shortstring): shortstring;[public,alias:'FPC_SHORTSTR_CONCAT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  507. var
  508. s1l, s2l : byte;
  509. begin
  510. s1l:=length(s1);
  511. s2l:=length(s2);
  512. if s1l+s2l>255 then
  513. s2l:=255-s1l;
  514. move(s1[1],fpc_shortstr_concat[1],s1l);
  515. move(s2[1],fpc_shortstr_concat[s1l+1],s2l);
  516. fpc_shortstr_concat[0]:=chr(s1l+s2l);
  517. end;
  518. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_CONCAT}
  519. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  520. procedure fpc_shortstr_append_shortstr(var s1:shortstring;const s2:shortstring);{$ifdef hascompilerproc} compilerproc; {$endif}
  521. [public,alias:'FPC_SHORTSTR_APPEND_SHORTSTR'];
  522. var
  523. s1l, s2l : byte;
  524. begin
  525. s1l:=length(s1);
  526. s2l:=length(s2);
  527. if s1l+s2l>high(s1) then
  528. s2l:=high(s1)-s1l;
  529. move(s2[1],s1[s1l+1],s2l);
  530. s1[0]:=chr(s1l+s2l);
  531. end;
  532. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_APPEND_SHORTSTR}
  533. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  534. function fpc_shortstr_compare(const left,right:shortstring) : longint;[public,alias:'FPC_SHORTSTR_COMPARE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  535. var
  536. s1,s2,max,i : byte;
  537. d : longint;
  538. begin
  539. s1:=length(left);
  540. s2:=length(right);
  541. if s1<s2 then
  542. max:=s1
  543. else
  544. max:=s2;
  545. for i:=1 to max do
  546. begin
  547. d:=byte(left[i])-byte(right[i]);
  548. if d>0 then
  549. exit(1)
  550. else if d<0 then
  551. exit(-1);
  552. end;
  553. if s1>s2 then
  554. exit(1)
  555. else if s1<s2 then
  556. exit(-1)
  557. else
  558. exit(0);
  559. end;
  560. {$endif ndef FPC_SYSTEM_HAS_FPC_SHORTSTR_COMPARE}
  561. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  562. function fpc_pchar_to_shortstr(p:pchar):shortstring;[public,alias:'FPC_PCHAR_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  563. var
  564. l : longint;
  565. s: shortstring;
  566. begin
  567. if p=nil then
  568. l:=0
  569. else
  570. l:=strlen(p);
  571. if l>255 then
  572. l:=255;
  573. if l>0 then
  574. move(p^,s[1],l);
  575. s[0]:=chr(l);
  576. fpc_pchar_to_shortstr := s;
  577. end;
  578. {$endif ndef FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
  579. {$ifndef FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  580. {$ifdef hascompilerproc}
  581. function fpc_chararray_to_shortstr(const arr: array of char):shortstring;[public,alias:'FPC_CHARARRAY_TO_SHORTSTR']; compilerproc;
  582. var
  583. l: longint;
  584. {$else hascompilerproc}
  585. function fpc_chararray_to_shortstr(arr:pchar; l : longint):shortstring;[public,alias:'FPC_CHARARRAY_TO_SHORTSTR'];
  586. var
  587. {$endif hascompilerproc}
  588. index: longint;
  589. len: byte;
  590. begin
  591. {$ifdef hascompilerproc}
  592. l := high(arr)+1;
  593. {$endif hascompilerproc}
  594. if l>=256 then
  595. l:=255
  596. else if l<0 then
  597. l:=0;
  598. index:=IndexByte(arr[0],l,0);
  599. if (index < 0) then
  600. len := l
  601. else
  602. len := index;
  603. move(arr[0],fpc_chararray_to_shortstr[1],len);
  604. fpc_chararray_to_shortstr[0]:=chr(len);
  605. end;
  606. {$endif ndef FPC_SYSTEM_HAS_FPC_CHARARRAY_TO_SHORTSTR}
  607. {$ifdef hascompilerproc}
  608. {$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_TO_CHARARRAY}
  609. { inside the compiler, the resulttype is modified to that of the actual }
  610. { chararray we're converting to (JM) }
  611. function fpc_shortstr_to_chararray(arraysize: longint; const src: ShortString): fpc_big_chararray;[public,alias: 'FPC_SHORTSTR_TO_CHARARRAY']; compilerproc;
  612. var
  613. len: longint;
  614. begin
  615. len := length(src);
  616. if len > arraysize then
  617. len := arraysize;
  618. { make sure we don't access char 1 if length is 0 (JM) }
  619. if len > 0 then
  620. move(src[1],fpc_shortstr_to_chararray[0],len);
  621. fillchar(fpc_shortstr_to_chararray[len],arraysize-len,0);
  622. end;
  623. {$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_TO_CHARARRAY}
  624. {$else hascompilerproc}
  625. {$ifopt r+}
  626. {$define rangeon}
  627. {$r-}
  628. {$endif}
  629. {$ifndef FPC_SYSTEM_HAS_FPC_STR_TO_CHARARRAY}
  630. procedure fpc_str_to_chararray(strtyp, arraysize: longint; src,dest: pchar);[public,alias:'FPC_STR_TO_CHARARRAY']; {$ifdef hascompilerproc} compilerproc; {$endif}
  631. type
  632. plongint = ^longint;
  633. var
  634. len: longint;
  635. begin
  636. case strtyp of
  637. { shortstring }
  638. 0:
  639. begin
  640. len := byte(src[0]);
  641. inc(src);
  642. end;
  643. {$ifdef SUPPORT_ANSISTRING}
  644. { ansistring}
  645. 1: len := length(ansistring(pointer(src)));
  646. {$endif SUPPORT_ANSISTRING}
  647. { longstring }
  648. 2:;
  649. { widestring }
  650. 3: ;
  651. end;
  652. if len > arraysize then
  653. len := arraysize;
  654. { make sure we don't dereference src if it can be nil (JM) }
  655. if len > 0 then
  656. move(src^,dest^,len);
  657. fillchar(dest[len],arraysize-len,0);
  658. end;
  659. {$endif FPC_SYSTEM_HAS_FPC_STR_TO_CHARARRAY}
  660. {$ifdef rangeon}
  661. {$r+}
  662. {undef rangeon}
  663. {$endif rangeon}
  664. {$endif hascompilerproc}
  665. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  666. function fpc_pchar_length(p:pchar):longint;[public,alias:'FPC_PCHAR_LENGTH']; {$ifdef hascompilerproc} compilerproc; {$endif}
  667. var i : longint;
  668. begin
  669. i:=0;
  670. while p[i]<>#0 do inc(i);
  671. exit(i);
  672. end;
  673. {$endif ndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  674. {$ifndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  675. function fpc_pwidechar_length(p:pwidechar):longint;[public,alias:'FPC_PWIDECHAR_LENGTH']; {$ifdef hascompilerproc} compilerproc; {$endif}
  676. var i : longint;
  677. begin
  678. i:=0;
  679. while p[i]<>#0 do inc(i);
  680. exit(i);
  681. end;
  682. {$endif ndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  683. {****************************************************************************
  684. Caller/StackFrame Helpers
  685. ****************************************************************************}
  686. {$ifndef FPC_SYSTEM_HAS_GET_FRAME}
  687. {_$error Get_frame must be defined for each processor }
  688. {$endif ndef FPC_SYSTEM_HAS_GET_FRAME}
  689. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  690. {_$error Get_caller_addr must be defined for each processor }
  691. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  692. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  693. {_$error Get_caller_frame must be defined for each processor }
  694. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  695. {****************************************************************************
  696. Math
  697. ****************************************************************************}
  698. {****************************************************************************
  699. Software longint/dword division
  700. ****************************************************************************}
  701. {$ifdef FPC_INCLUDE_SOFTWARE_MOD_DIV}
  702. function count_leading_zeros_32bit(l : longint) : longint;
  703. var
  704. i : longint;
  705. begin
  706. for i:=0 to 31 do
  707. begin
  708. if (l and (longint($80000000) shr i))<>0 then
  709. begin
  710. result:=i;
  711. exit;
  712. end;
  713. end;
  714. result:=i;
  715. end;
  716. {$ifndef FPC_SYSTEM_HAS_DIV_DWORD}
  717. function fpc_div_dword(n,z : dword) : dword; [public,alias: 'FPC_DIV_DWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  718. var
  719. shift,lzz,lzn : longint;
  720. begin
  721. result:=0;
  722. if n=0 then
  723. HandleErrorFrame(200,get_frame);
  724. lzz:=count_leading_zeros_32bit(z);
  725. lzn:=count_leading_zeros_32bit(n);
  726. { if the denominator contains less zeros
  727. then the numerator
  728. the d is greater than the n }
  729. if lzn<lzz then
  730. exit;
  731. shift:=lzn-lzz;
  732. n:=n shl shift;
  733. repeat
  734. if z>=n then
  735. begin
  736. z:=z-n;
  737. result:=result+dword(1 shl shift);
  738. end;
  739. dec(shift);
  740. n:=n shr 1;
  741. until shift<0;
  742. end;
  743. {$endif FPC_SYSTEM_HAS_DIV_DWORD}
  744. {$ifndef FPC_SYSTEM_HAS_MOD_DWORD}
  745. function fpc_mod_dword(n,z : dword) : dword; [public,alias: 'FPC_MOD_DWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  746. var
  747. shift,lzz,lzn : longint;
  748. begin
  749. result:=0;
  750. if n=0 then
  751. HandleErrorFrame(200,get_frame);
  752. lzz:=count_leading_zeros_32bit(z);
  753. lzn:=count_leading_zeros_32bit(n);
  754. { if the denominator contains less zeros
  755. then the numerator
  756. the d is greater than the n }
  757. if lzn<lzz then
  758. begin
  759. result:=z;
  760. exit;
  761. end;
  762. shift:=lzn-lzz;
  763. n:=n shl shift;
  764. repeat
  765. if z>=n then
  766. z:=z-n;
  767. dec(shift);
  768. n:=n shr 1;
  769. until shift<0;
  770. result:=z;
  771. end;
  772. {$endif FPC_SYSTEM_HAS_MOD_DWORD}
  773. {$ifndef FPC_SYSTEM_HAS_DIV_LONGINT}
  774. function fpc_div_longint(n,z : longint) : longint; [public,alias: 'FPC_DIV_LONGINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  775. var
  776. sign : boolean;
  777. d1,d2 : dword;
  778. begin
  779. if n=0 then
  780. HandleErrorFrame(200,get_frame);
  781. sign:=false;
  782. if z<0 then
  783. begin
  784. sign:=not(sign);
  785. d1:=dword(-z);
  786. end
  787. else
  788. d1:=z;
  789. if n<0 then
  790. begin
  791. sign:=not(sign);
  792. d2:=dword(-n);
  793. end
  794. else
  795. d2:=n;
  796. { the div is coded by the compiler as call to divdword }
  797. if sign then
  798. result:=-(d1 div d2)
  799. else
  800. result:=d1 div d2;
  801. end;
  802. {$endif FPC_SYSTEM_HAS_DIV_LONGINT}
  803. {$ifndef FPC_SYSTEM_HAS_MOD_LONGINT}
  804. function fpc_mod_longint(n,z : longint) : longint; [public,alias: 'FPC_MOD_LONGINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  805. var
  806. signed : boolean;
  807. r,nq,zq : dword;
  808. begin
  809. if n=0 then
  810. HandleErrorFrame(200,get_frame);
  811. nq:=abs(n);
  812. if z<0 then
  813. begin
  814. zq:=dword(-z);
  815. signed:=true;
  816. end
  817. else
  818. begin
  819. zq:=z;
  820. signed:=false;
  821. end;
  822. r:=zq mod nq;
  823. if signed then
  824. result:=-longint(r)
  825. else
  826. result:=r;
  827. end;
  828. {$endif FPC_SYSTEM_HAS_MOD_LONGINT}
  829. {$endif FPC_INCLUDE_SOFTWARE_MOD_DIV}
  830. {****************************************************************************}
  831. {$ifndef FPC_SYSTEM_HAS_ABS_LONGINT}
  832. function abs(l:longint):longint;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_abs];{$endif}
  833. begin
  834. if l<0 then
  835. abs:=-l
  836. else
  837. abs:=l;
  838. end;
  839. {$endif not FPC_SYSTEM_HAS_ABS_LONGINT}
  840. {$ifndef FPC_SYSTEM_HAS_ODD_LONGINT}
  841. function odd(l:longint):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_odd];{$endif}
  842. begin
  843. odd:=boolean(l and 1);
  844. end;
  845. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGINT}
  846. {$ifndef FPC_SYSTEM_HAS_ODD_LONGWORD}
  847. function odd(l:longword):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_odd];{$endif}
  848. begin
  849. odd:=boolean(l and 1);
  850. end;
  851. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGWORD}
  852. {$ifndef FPC_SYSTEM_HAS_ODD_INT64}
  853. function odd(l:int64):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_odd];{$endif}
  854. begin
  855. odd:=boolean(longint(l) and 1);
  856. end;
  857. {$endif ndef FPC_SYSTEM_HAS_ODD_INT64}
  858. {$ifndef FPC_SYSTEM_HAS_ODD_QWORD}
  859. function odd(l:qword):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_odd];{$endif}
  860. begin
  861. odd:=boolean(longint(l) and 1);
  862. end;
  863. {$endif ndef FPC_SYSTEM_HAS_ODD_QWORD}
  864. {$ifndef FPC_SYSTEM_HAS_SQR_LONGINT}
  865. function sqr(l:longint):longint;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_sqr];{$endif}
  866. begin
  867. sqr:=l*l;
  868. end;
  869. {$endif ndef FPC_SYSTEM_HAS_SQR_LONGINT}
  870. {$ifndef FPC_SYSTEM_HAS_ABS_INT64}
  871. function abs(l: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_abs];{$endif}
  872. begin
  873. if l < 0 then
  874. abs := -l
  875. else
  876. abs := l;
  877. end;
  878. {$endif ndef FPC_SYSTEM_HAS_ABS_INT64}
  879. {$ifndef FPC_SYSTEM_HAS_SQR_INT64}
  880. function sqr(l: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_sqr];{$endif}
  881. begin
  882. sqr := l*l;
  883. end;
  884. {$endif ndef FPC_SYSTEM_HAS_SQR_INT64}
  885. {$ifndef FPC_SYSTEM_HAS_SQR_QWORD}
  886. function sqr(l: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_sqr];{$endif}
  887. begin
  888. sqr := l*l;
  889. end;
  890. {$endif ndef FPC_SYSTEM_HAS_SQR_INT64}
  891. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  892. function declocked(var l:longint):boolean;
  893. begin
  894. Dec(l);
  895. declocked:=(l=0);
  896. end;
  897. {$endif FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  898. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_INT64}
  899. function declocked(var l:int64):boolean;
  900. begin
  901. Dec(l);
  902. declocked:=(l=0);
  903. end;
  904. {$endif FPC_SYSTEM_HAS_DECLOCKED_INT64}
  905. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  906. procedure inclocked(var l:longint);
  907. begin
  908. Inc(l);
  909. end;
  910. {$endif FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  911. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_INT64}
  912. procedure inclocked(var l:int64);
  913. begin
  914. Inc(l);
  915. end;
  916. {$endif FPC_SYSTEM_HAS_INCLOCKED_INT64}
  917. {$ifndef FPC_SYSTEM_HAS_SPTR}
  918. {_$error Sptr must be defined for each processor }
  919. {$endif ndef FPC_SYSTEM_HAS_SPTR}
  920. {$ifndef INTERNCONSTINTF}
  921. procedure prefetch(const mem);[internproc:fpc_in_prefetch_var];
  922. {$endif}
  923. function align(addr : PtrInt;alignment : PtrInt) : PtrInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  924. begin
  925. if addr mod alignment<>0 then
  926. result:=addr+(alignment-(addr mod alignment))
  927. else
  928. result:=addr;
  929. end;
  930. function align(addr : Pointer;alignment : PtrInt) : Pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
  931. begin
  932. if PtrInt(addr) mod alignment<>0 then
  933. result:=pointer(addr+(alignment-(PtrInt(addr) mod alignment)))
  934. else
  935. result:=addr;
  936. end;
  937. {****************************************************************************
  938. Str()
  939. ****************************************************************************}
  940. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  941. procedure int_str(l : longint;var s : string);
  942. var
  943. value: longint;
  944. negative: boolean;
  945. begin
  946. negative := false;
  947. s:='';
  948. { Workaround: }
  949. if l=longint($80000000) then
  950. begin
  951. s:='-2147483648';
  952. exit;
  953. end;
  954. { handle case where l = 0 }
  955. if l = 0 then
  956. begin
  957. s:='0';
  958. exit;
  959. end;
  960. If l < 0 then
  961. begin
  962. negative := true;
  963. value:=abs(l);
  964. end
  965. else
  966. value:=l;
  967. { handle non-zero case }
  968. while value>0 do
  969. begin
  970. s:=char((value mod 10)+ord('0'))+s;
  971. value := value div 10;
  972. end;
  973. if negative then
  974. s := '-' + s;
  975. end;
  976. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  977. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  978. procedure int_str(l : longword;var s : string);
  979. begin
  980. s:='';
  981. if l = 0 then
  982. begin
  983. s := '0';
  984. exit;
  985. end;
  986. while l>0 do
  987. begin
  988. s:=char(ord('0')+(l mod 10))+s;
  989. l:=l div 10;
  990. end;
  991. end;
  992. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  993. {$ifndef FPC_SYSTEM_HAS_INT_STR_INT64}
  994. procedure int_str(l : int64;var s : string);
  995. var
  996. value: int64;
  997. negative: boolean;
  998. begin
  999. negative := false;
  1000. s:='';
  1001. { Workaround: }
  1002. if l=int64($8000000000000000) then
  1003. begin
  1004. s:='-9223372036854775808';
  1005. exit;
  1006. end;
  1007. { handle case where l = 0 }
  1008. if l = 0 then
  1009. begin
  1010. s:='0';
  1011. exit;
  1012. end;
  1013. If l < 0 then
  1014. begin
  1015. negative := true;
  1016. value:=abs(l);
  1017. end
  1018. else
  1019. value:=l;
  1020. { handle non-zero case }
  1021. while value>0 do
  1022. begin
  1023. s:=char((value mod 10)+ord('0'))+s;
  1024. value := value div 10;
  1025. end;
  1026. if negative then
  1027. s := '-' + s;
  1028. end;
  1029. {$endif ndef FPC_SYSTEM_HAS_INT_STR_INT64}
  1030. {$ifndef FPC_SYSTEM_HAS_INT_STR_QWORD}
  1031. procedure int_str(l : qword;var s : string);
  1032. begin
  1033. s:='';
  1034. if l = 0 then
  1035. begin
  1036. s := '0';
  1037. exit;
  1038. end;
  1039. while l>0 do
  1040. begin
  1041. s:=char(ord('0')+(l mod 10))+s;
  1042. l:=l div 10;
  1043. end;
  1044. end;
  1045. {$endif ndef FPC_SYSTEM_HAS_INT_STR_QWORD}
  1046. {$ifndef FPC_SYSTEM_HAS_SYSRESETFPU}
  1047. procedure SysResetFpu;{$ifdef SYSTEMINLINE}inline;{$endif}
  1048. begin
  1049. { nothing todo }
  1050. end;
  1051. {$endif FPC_SYSTEM_HAS_SYSRESETFPU}