generic.inc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242
  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. {$ifdef HASWIDESTRING}
  675. {$ifndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  676. function fpc_pwidechar_length(p:pwidechar):longint;[public,alias:'FPC_PWIDECHAR_LENGTH']; {$ifdef hascompilerproc} compilerproc; {$endif}
  677. var i : longint;
  678. begin
  679. i:=0;
  680. while p[i]<>#0 do inc(i);
  681. exit(i);
  682. end;
  683. {$endif ndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  684. {$endif HASWIDESTRING}
  685. {****************************************************************************
  686. Caller/StackFrame Helpers
  687. ****************************************************************************}
  688. {$ifndef FPC_SYSTEM_HAS_GET_FRAME}
  689. {_$error Get_frame must be defined for each processor }
  690. {$endif ndef FPC_SYSTEM_HAS_GET_FRAME}
  691. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  692. {_$error Get_caller_addr must be defined for each processor }
  693. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  694. {$ifndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  695. {_$error Get_caller_frame must be defined for each processor }
  696. {$endif ndef FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  697. {****************************************************************************
  698. Math
  699. ****************************************************************************}
  700. {****************************************************************************
  701. Software longint/dword division
  702. ****************************************************************************}
  703. {$ifdef FPC_INCLUDE_SOFTWARE_MOD_DIV}
  704. function count_leading_zeros_32bit(l : longint) : longint;
  705. var
  706. i : longint;
  707. begin
  708. for i:=0 to 31 do
  709. begin
  710. if (l and (longint($80000000) shr i))<>0 then
  711. begin
  712. result:=i;
  713. exit;
  714. end;
  715. end;
  716. result:=i;
  717. end;
  718. {$ifndef FPC_SYSTEM_HAS_DIV_DWORD}
  719. function fpc_div_dword(n,z : dword) : dword; [public,alias: 'FPC_DIV_DWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  720. var
  721. shift,lzz,lzn : longint;
  722. begin
  723. result:=0;
  724. if n=0 then
  725. HandleErrorFrame(200,get_frame);
  726. lzz:=count_leading_zeros_32bit(z);
  727. lzn:=count_leading_zeros_32bit(n);
  728. { if the denominator contains less zeros
  729. then the numerator
  730. the d is greater than the n }
  731. if lzn<lzz then
  732. exit;
  733. shift:=lzn-lzz;
  734. n:=n shl shift;
  735. repeat
  736. if z>=n then
  737. begin
  738. z:=z-n;
  739. result:=result+dword(1 shl shift);
  740. end;
  741. dec(shift);
  742. n:=n shr 1;
  743. until shift<0;
  744. end;
  745. {$endif FPC_SYSTEM_HAS_DIV_DWORD}
  746. {$ifndef FPC_SYSTEM_HAS_MOD_DWORD}
  747. function fpc_mod_dword(n,z : dword) : dword; [public,alias: 'FPC_MOD_DWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  748. var
  749. shift,lzz,lzn : longint;
  750. begin
  751. result:=0;
  752. if n=0 then
  753. HandleErrorFrame(200,get_frame);
  754. lzz:=count_leading_zeros_32bit(z);
  755. lzn:=count_leading_zeros_32bit(n);
  756. { if the denominator contains less zeros
  757. then the numerator
  758. the d is greater than the n }
  759. if lzn<lzz then
  760. begin
  761. result:=z;
  762. exit;
  763. end;
  764. shift:=lzn-lzz;
  765. n:=n shl shift;
  766. repeat
  767. if z>=n then
  768. z:=z-n;
  769. dec(shift);
  770. n:=n shr 1;
  771. until shift<0;
  772. result:=z;
  773. end;
  774. {$endif FPC_SYSTEM_HAS_MOD_DWORD}
  775. {$ifndef FPC_SYSTEM_HAS_DIV_LONGINT}
  776. function fpc_div_longint(n,z : longint) : longint; [public,alias: 'FPC_DIV_LONGINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  777. var
  778. sign : boolean;
  779. d1,d2 : dword;
  780. begin
  781. if n=0 then
  782. HandleErrorFrame(200,get_frame);
  783. sign:=false;
  784. if z<0 then
  785. begin
  786. sign:=not(sign);
  787. d1:=dword(-z);
  788. end
  789. else
  790. d1:=z;
  791. if n<0 then
  792. begin
  793. sign:=not(sign);
  794. d2:=dword(-n);
  795. end
  796. else
  797. d2:=n;
  798. { the div is coded by the compiler as call to divdword }
  799. if sign then
  800. result:=-(d1 div d2)
  801. else
  802. result:=d1 div d2;
  803. end;
  804. {$endif FPC_SYSTEM_HAS_DIV_LONGINT}
  805. {$ifndef FPC_SYSTEM_HAS_MOD_LONGINT}
  806. function fpc_mod_longint(n,z : longint) : longint; [public,alias: 'FPC_MOD_LONGINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  807. var
  808. signed : boolean;
  809. r,nq,zq : dword;
  810. begin
  811. if n=0 then
  812. HandleErrorFrame(200,get_frame);
  813. nq:=abs(n);
  814. if z<0 then
  815. begin
  816. zq:=dword(-z);
  817. signed:=true;
  818. end
  819. else
  820. begin
  821. zq:=z;
  822. signed:=false;
  823. end;
  824. r:=zq mod nq;
  825. if signed then
  826. result:=-longint(r)
  827. else
  828. result:=r;
  829. end;
  830. {$endif FPC_SYSTEM_HAS_MOD_LONGINT}
  831. {$endif FPC_INCLUDE_SOFTWARE_MOD_DIV}
  832. {****************************************************************************}
  833. {$ifndef FPC_SYSTEM_HAS_ABS_LONGINT}
  834. function abs(l:longint):longint;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_abs];{$endif}
  835. begin
  836. if l<0 then
  837. abs:=-l
  838. else
  839. abs:=l;
  840. end;
  841. {$endif not FPC_SYSTEM_HAS_ABS_LONGINT}
  842. {$ifndef FPC_SYSTEM_HAS_ODD_LONGINT}
  843. function odd(l:longint):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_odd];{$endif}
  844. begin
  845. odd:=boolean(l and 1);
  846. end;
  847. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGINT}
  848. {$ifndef FPC_SYSTEM_HAS_ODD_LONGWORD}
  849. function odd(l:longword):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_odd];{$endif}
  850. begin
  851. odd:=boolean(l and 1);
  852. end;
  853. {$endif ndef FPC_SYSTEM_HAS_ODD_LONGWORD}
  854. {$ifndef FPC_SYSTEM_HAS_ODD_INT64}
  855. function odd(l:int64):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_odd];{$endif}
  856. begin
  857. odd:=boolean(longint(l) and 1);
  858. end;
  859. {$endif ndef FPC_SYSTEM_HAS_ODD_INT64}
  860. {$ifndef FPC_SYSTEM_HAS_ODD_QWORD}
  861. function odd(l:qword):boolean;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_odd];{$endif}
  862. begin
  863. odd:=boolean(longint(l) and 1);
  864. end;
  865. {$endif ndef FPC_SYSTEM_HAS_ODD_QWORD}
  866. {$ifndef FPC_SYSTEM_HAS_SQR_LONGINT}
  867. function sqr(l:longint):longint;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_sqr];{$endif}
  868. begin
  869. sqr:=l*l;
  870. end;
  871. {$endif ndef FPC_SYSTEM_HAS_SQR_LONGINT}
  872. {$ifndef FPC_SYSTEM_HAS_ABS_INT64}
  873. function abs(l: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_abs];{$endif}
  874. begin
  875. if l < 0 then
  876. abs := -l
  877. else
  878. abs := l;
  879. end;
  880. {$endif ndef FPC_SYSTEM_HAS_ABS_INT64}
  881. {$ifndef FPC_SYSTEM_HAS_SQR_INT64}
  882. function sqr(l: Int64): Int64;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_sqr];{$endif}
  883. begin
  884. sqr := l*l;
  885. end;
  886. {$endif ndef FPC_SYSTEM_HAS_SQR_INT64}
  887. {$ifndef FPC_SYSTEM_HAS_SQR_QWORD}
  888. function sqr(l: QWord): QWord;{$ifdef SYSTEMINLINE}inline;{$endif}{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_sqr];{$endif}
  889. begin
  890. sqr := l*l;
  891. end;
  892. {$endif ndef FPC_SYSTEM_HAS_SQR_INT64}
  893. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  894. function declocked(var l:longint):boolean;
  895. begin
  896. Dec(l);
  897. declocked:=(l=0);
  898. end;
  899. {$endif FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  900. {$ifndef FPC_SYSTEM_HAS_DECLOCKED_INT64}
  901. function declocked(var l:int64):boolean;
  902. begin
  903. Dec(l);
  904. declocked:=(l=0);
  905. end;
  906. {$endif FPC_SYSTEM_HAS_DECLOCKED_INT64}
  907. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  908. procedure inclocked(var l:longint);
  909. begin
  910. Inc(l);
  911. end;
  912. {$endif FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  913. {$ifndef FPC_SYSTEM_HAS_INCLOCKED_INT64}
  914. procedure inclocked(var l:int64);
  915. begin
  916. Inc(l);
  917. end;
  918. {$endif FPC_SYSTEM_HAS_INCLOCKED_INT64}
  919. {$ifndef FPC_SYSTEM_HAS_SPTR}
  920. {_$error Sptr must be defined for each processor }
  921. {$endif ndef FPC_SYSTEM_HAS_SPTR}
  922. {$ifndef INTERNCONSTINTF}
  923. procedure prefetch(const mem);[internproc:fpc_in_prefetch_var];
  924. {$endif}
  925. function align(addr : PtrInt;alignment : PtrInt) : PtrInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  926. begin
  927. if addr mod alignment<>0 then
  928. result:=addr+(alignment-(addr mod alignment))
  929. else
  930. result:=addr;
  931. end;
  932. function align(addr : Pointer;alignment : PtrInt) : Pointer;{$ifdef SYSTEMINLINE}inline;{$endif}
  933. begin
  934. if PtrInt(addr) mod alignment<>0 then
  935. result:=pointer(addr+(alignment-(PtrInt(addr) mod alignment)))
  936. else
  937. result:=addr;
  938. end;
  939. {****************************************************************************
  940. Str()
  941. ****************************************************************************}
  942. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  943. procedure int_str(l : longint;var s : string);
  944. var
  945. value: longint;
  946. negative: boolean;
  947. begin
  948. negative := false;
  949. s:='';
  950. { Workaround: }
  951. if l=longint($80000000) then
  952. begin
  953. s:='-2147483648';
  954. exit;
  955. end;
  956. { handle case where l = 0 }
  957. if l = 0 then
  958. begin
  959. s:='0';
  960. exit;
  961. end;
  962. If l < 0 then
  963. begin
  964. negative := true;
  965. value:=abs(l);
  966. end
  967. else
  968. value:=l;
  969. { handle non-zero case }
  970. while value>0 do
  971. begin
  972. s:=char((value mod 10)+ord('0'))+s;
  973. value := value div 10;
  974. end;
  975. if negative then
  976. s := '-' + s;
  977. end;
  978. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
  979. {$ifndef FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  980. procedure int_str(l : longword;var s : string);
  981. begin
  982. s:='';
  983. if l = 0 then
  984. begin
  985. s := '0';
  986. exit;
  987. end;
  988. while l>0 do
  989. begin
  990. s:=char(ord('0')+(l mod 10))+s;
  991. l:=l div 10;
  992. end;
  993. end;
  994. {$endif ndef FPC_SYSTEM_HAS_INT_STR_LONGWORD}
  995. {$ifndef FPC_SYSTEM_HAS_INT_STR_INT64}
  996. procedure int_str(l : int64;var s : string);
  997. var
  998. value: int64;
  999. negative: boolean;
  1000. begin
  1001. negative := false;
  1002. s:='';
  1003. { Workaround: }
  1004. {$ifdef ver1_0}
  1005. if (l shr 32=$80000000) and ((l and $ffffffff)=0) then
  1006. {$else}
  1007. if l=int64($8000000000000000) then
  1008. {$endif}
  1009. begin
  1010. s:='-9223372036854775808';
  1011. exit;
  1012. end;
  1013. { handle case where l = 0 }
  1014. if l = 0 then
  1015. begin
  1016. s:='0';
  1017. exit;
  1018. end;
  1019. If l < 0 then
  1020. begin
  1021. negative := true;
  1022. value:=abs(l);
  1023. end
  1024. else
  1025. value:=l;
  1026. { handle non-zero case }
  1027. while value>0 do
  1028. begin
  1029. s:=char((value mod 10)+ord('0'))+s;
  1030. value := value div 10;
  1031. end;
  1032. if negative then
  1033. s := '-' + s;
  1034. end;
  1035. {$endif ndef FPC_SYSTEM_HAS_INT_STR_INT64}
  1036. {$ifndef FPC_SYSTEM_HAS_INT_STR_QWORD}
  1037. procedure int_str(l : qword;var s : string);
  1038. begin
  1039. s:='';
  1040. if l = 0 then
  1041. begin
  1042. s := '0';
  1043. exit;
  1044. end;
  1045. while l>0 do
  1046. begin
  1047. s:=char(ord('0')+(l mod 10))+s;
  1048. l:=l div 10;
  1049. end;
  1050. end;
  1051. {$endif ndef FPC_SYSTEM_HAS_INT_STR_QWORD}
  1052. {$ifndef FPC_SYSTEM_HAS_SYSRESETFPU}
  1053. procedure SysResetFpu;{$ifdef SYSTEMINLINE}inline;{$endif}
  1054. begin
  1055. { nothing todo }
  1056. end;
  1057. {$endif FPC_SYSTEM_HAS_SYSRESETFPU}
  1058. {
  1059. $Log: generic.inc,v $
  1060. Revision 1.90 2005/02/14 17:13:22 peter
  1061. * truncate log
  1062. }