generic.inc 27 KB

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