system.inc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. For details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************
  12. Local types
  13. ****************************************************************************}
  14. {
  15. TextRec and FileRec are put in a separate file to make it available to other
  16. units without putting it explicitly in systemh.
  17. This way we keep TP compatibility, and the TextRec definition is available
  18. for everyone who needs it.
  19. }
  20. {$i filerec.inc}
  21. {$i textrec.inc}
  22. Procedure HandleError (Errno : Longint); forward;
  23. Procedure HandleErrorFrame (Errno : longint;frame : longint); forward;
  24. type
  25. FileFunc = Procedure(var t : TextRec);
  26. const
  27. STACK_MARGIN = 16384; { Stack size margin for stack checking }
  28. { Random / Randomize constants }
  29. OldRandSeed : Cardinal = 0;
  30. InitialSeed : Boolean = TRUE;
  31. Seed2 : Cardinal = 0;
  32. Seed3 : Cardinal = 0;
  33. { For Error Handling.}
  34. ErrorBase : Longint = 0;
  35. { Used by the ansistrings and maybe also other things in the future }
  36. var
  37. emptychar : char;public name 'FPC_EMPTYCHAR';
  38. initialstklen : longint;external name '__stklen';
  39. {****************************************************************************
  40. Routines which have compiler magic
  41. ****************************************************************************}
  42. {$I innr.inc}
  43. Function lo(i : Integer) : byte; [INTERNPROC: In_lo_Word];
  44. Function lo(w : Word) : byte; [INTERNPROC: In_lo_Word];
  45. Function lo(l : Longint) : Word; [INTERNPROC: In_lo_long];
  46. Function lo(l : DWord) : Word; [INTERNPROC: In_lo_long];
  47. Function hi(i : Integer) : byte; [INTERNPROC: In_hi_Word];
  48. Function hi(w : Word) : byte; [INTERNPROC: In_hi_Word];
  49. Function hi(l : Longint) : Word; [INTERNPROC: In_hi_long];
  50. Function hi(l : DWord) : Word; [INTERNPROC: In_hi_long];
  51. Function lo(q : QWord) : DWord; [INTERNPROC: In_lo_qword];
  52. Function lo(i : Int64) : DWord; [INTERNPROC: In_lo_qword];
  53. Function hi(q : QWord) : DWord; [INTERNPROC: In_hi_qword];
  54. Function hi(i : Int64) : DWord; [INTERNPROC: In_hi_qword];
  55. Function chr(b : byte) : Char; [INTERNPROC: In_chr_byte];
  56. {$ifndef INTERNLENGTH}
  57. Function Length(s : string) : byte; [INTERNPROC: In_Length_string];
  58. Function Length(c : char) : byte; [INTERNPROC: In_Length_string];
  59. {$endif INTERNLENGTH}
  60. Procedure Reset(var f : TypedFile); [INTERNPROC: In_Reset_TypedFile];
  61. Procedure Rewrite(var f : TypedFile); [INTERNPROC: In_Rewrite_TypedFile];
  62. {****************************************************************************
  63. Include processor specific routines
  64. ****************************************************************************}
  65. {$ifdef i386}
  66. {$ifdef SYSPROCDEFINED}
  67. {$Error Can't determine processor type !}
  68. {$endif}
  69. {$define ENDIAN_LITTLE}
  70. {$i i386.inc} { Case dependent, don't change }
  71. {$endif i386}
  72. {$ifdef m68k}
  73. {$ifdef SYSPROCDEFINED}
  74. {$Error Can't determine processor type !}
  75. {$endif}
  76. {$define ENDIAN_BIG}
  77. {$i m68k.inc} { Case dependent, don't change }
  78. {$define SYSPROCDEFINED}
  79. {$endif m68k}
  80. {$ifdef x86_64}
  81. {$ifdef SYSPROCDEFINED}
  82. {$Error Can't determine processor type !}
  83. {$endif}
  84. {$define ENDIAN_LITTLE}
  85. {$i x86_64.inc} { Case dependent, don't change }
  86. {$define SYSPROCDEFINED}
  87. {$endif x86_64}
  88. {$ifdef powerpc}
  89. {$ifdef SYSPROCDEFINED}
  90. {$Error Can't determine processor type !}
  91. {$endif}
  92. {$define ENDIAN_BIG}
  93. {$i powerpc.inc} { Case dependent, don't change }
  94. {$define SYSPROCDEFINED}
  95. {$endif powerpc}
  96. {$ifdef alpha}
  97. {$ifdef SYSPROCDEFINED}
  98. {$Error Can't determine processor type !}
  99. {$endif}
  100. {$define ENDIAN_BIG}
  101. {$i alpha.inc} { Case dependent, don't change }
  102. {$define SYSPROCDEFINED}
  103. {$endif alpha}
  104. {$ifdef iA64}
  105. {$ifdef SYSPROCDEFINED}
  106. {$Error Can't determine processor type !}
  107. {$endif}
  108. {$define ENDIAN_LITTLE}
  109. {$i ia64.inc} { Case dependent, don't change }
  110. {$define SYSPROCDEFINED}
  111. {$endif iA64}
  112. procedure fillchar(var x;count : longint;value : boolean);{$ifdef SYSTEMINLINE}inline;{$endif}
  113. begin
  114. fillchar(x,count,byte(value));
  115. end;
  116. procedure fillchar(var x;count : longint;value : char);{$ifdef SYSTEMINLINE}inline;{$endif}
  117. begin
  118. fillchar(x,count,byte(value));
  119. end;
  120. { Include generic pascal only routines which are not defined in the processor
  121. specific include file }
  122. {$I generic.inc}
  123. {****************************************************************************
  124. Set Handling
  125. ****************************************************************************}
  126. { Include set support which is processor specific}
  127. {$i set.inc}
  128. { Include generic pascal routines for sets if the processor }
  129. { specific routines are not available. }
  130. {$i genset.inc}
  131. {****************************************************************************
  132. Math Routines
  133. ****************************************************************************}
  134. function Hi(b : byte): byte;{$ifdef SYSTEMINLINE}inline;{$endif}
  135. begin
  136. Hi := b shr 4
  137. end;
  138. function Lo(b : byte): byte;{$ifdef SYSTEMINLINE}inline;{$endif}
  139. begin
  140. Lo := b and $0f
  141. end;
  142. Function swap (X : Word) : Word;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_swap_word];
  143. Begin
  144. swap:=(X and $ff) shl 8 + (X shr 8)
  145. End;
  146. Function Swap (X : Integer) : Integer;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_swap_word];
  147. Begin
  148. swap:=(X and $ff) shl 8 + (X shr 8)
  149. End;
  150. Function swap (X : Longint) : Longint;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_swap_long];
  151. Begin
  152. Swap:=(X and $ffff) shl 16 + (X shr 16)
  153. End;
  154. Function Swap (X : Cardinal) : Cardinal;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_swap_long];
  155. Begin
  156. Swap:=(X and $ffff) shl 16 + (X shr 16)
  157. End;
  158. Function Swap (X : QWord) : QWord;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_swap_qword];
  159. Begin
  160. Swap:=(X and $ffffffff) shl 32 + (X shr 32);
  161. End;
  162. Function swap (X : Int64) : Int64;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_swap_qword];
  163. Begin
  164. Swap:=(X and $ffffffff) shl 32 + (X shr 32);
  165. End;
  166. operator := (b:real48) d:double;
  167. begin
  168. D:=real2double(b);
  169. end;
  170. {$ifdef SUPPORT_EXTENDED}
  171. operator := (b:real48) e:extended;
  172. begin
  173. e:=real2double(b);
  174. end;
  175. {$endif SUPPORT_EXTENDED}
  176. { Include processor specific routines }
  177. {$I math.inc}
  178. { Include generic version }
  179. {$I genmath.inc}
  180. {****************************************************************************
  181. Subroutines for String handling
  182. ****************************************************************************}
  183. { Needs to be before RTTI handling }
  184. {$i sstrings.inc}
  185. { requires sstrings.inc for initval }
  186. {$I int64.inc}
  187. {Requires int64.inc, since that contains the VAL functions for int64 and qword}
  188. {$i astrings.inc}
  189. {$ifdef HASWIDESTRING}
  190. {$i wstrings.inc}
  191. {$endif HASWIDESTRING}
  192. {$i aliases.inc}
  193. {*****************************************************************************
  194. Dynamic Array support
  195. *****************************************************************************}
  196. {$i dynarr.inc}
  197. {*****************************************************************************
  198. Object Pascal support
  199. *****************************************************************************}
  200. {$i objpas.inc}
  201. {*****************************************************************************
  202. Variant support
  203. *****************************************************************************}
  204. {$ifdef HASVARIANT}
  205. {$i variant.inc}
  206. {$endif HASVARIANT}
  207. {****************************************************************************
  208. Run-Time Type Information (RTTI)
  209. ****************************************************************************}
  210. {$i rtti.inc}
  211. {****************************************************************************
  212. Random function routines
  213. This implements a very long cycle random number generator by combining
  214. three independant generators. The technique was described in the March
  215. 1987 issue of Byte.
  216. Taken and modified with permission from the PCQ Pascal rtl code.
  217. ****************************************************************************}
  218. {$R-}
  219. {$Q-}
  220. Procedure NewSeed;Forward;
  221. Function Random : Extended;
  222. begin
  223. if (InitialSeed) OR (RandSeed <> OldRandSeed) then
  224. Begin
  225. { This is a pretty complicated affair }
  226. { Initially we must call NewSeed when RandSeed is initalized }
  227. { We must also call NewSeed each time RandSeed is reinitialized }
  228. { DO NOT CHANGE THE ORDER OF DECLARATIONS IN THIS BLOCK }
  229. { UNLESS YOU WANT RANDON TO CRASH OF COURSE (CEC) }
  230. InitialSeed:=FALSE;
  231. OldRandSeed:=RandSeed;
  232. NewSeed;
  233. end;
  234. Inc(RandSeed);
  235. RandSeed := (RandSeed * 706) mod 500009;
  236. OldRandSeed:=RandSeed;
  237. INC(Seed2);
  238. Seed2 := (Seed2 * 774) MOD 600011;
  239. INC(Seed3);
  240. Seed3 := (Seed3 * 871) MOD 765241;
  241. Random :=
  242. frac(RandSeed/500009.0 +
  243. Seed2/600011.0 +
  244. Seed3/765241.0);
  245. end;
  246. Function internRandom(l : Cardinal) : Cardinal;
  247. begin
  248. if (InitialSeed) OR (RandSeed <> OldRandSeed) then
  249. Begin
  250. { This is a pretty complicated affair }
  251. { Initially we must call NewSeed when RandSeed is initalized }
  252. { We must also call NewSeed each time RandSeed is reinitialized }
  253. { DO NOT CHANGE THE ORDER OF DECLARATIONS IN THIS BLOCK }
  254. { UNLESS YOU WANT RANDOM TO CRASH OF COURSE (CEC) }
  255. InitialSeed:=FALSE;
  256. OldRandSeed:=RandSeed;
  257. NewSeed;
  258. end;
  259. Inc(RandSeed);
  260. RandSeed := (RandSeed * 998) mod 1000003;
  261. OldRandSeed:=RandSeed;
  262. if l<>0 then
  263. begin
  264. internRandom := RandSeed mod l;
  265. end
  266. else internRandom:=0;
  267. end;
  268. function random(l:cardinal): cardinal;
  269. begin
  270. random := trunc(random()*l);
  271. end;
  272. function random(l:longint): longint;
  273. begin
  274. random := trunc(random()*l);
  275. end;
  276. Procedure NewSeed;
  277. begin
  278. randseed := randseed mod 1000003;
  279. Seed2 := (internRandom(65000) * internRandom(65000)) mod 600011;
  280. Seed3 := (internRandom(65000) * internRandom(65000)) mod 765241;
  281. end;
  282. {****************************************************************************
  283. Memory Management
  284. ****************************************************************************}
  285. Function Ptr(sel,off : Longint) : farpointer;{$ifdef SYSTEMINLINE}inline;{$endif}[internconst:in_const_ptr];
  286. Begin
  287. ptr:=farpointer((sel shl 4)+off);
  288. End;
  289. Function CSeg : Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  290. Begin
  291. Cseg:=0;
  292. End;
  293. Function DSeg : Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  294. Begin
  295. Dseg:=0;
  296. End;
  297. Function SSeg : Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  298. Begin
  299. Sseg:=0;
  300. End;
  301. {*****************************************************************************
  302. Directory support.
  303. *****************************************************************************}
  304. Procedure getdir(drivenr:byte;Var dir:ansistring);
  305. { this is needed to also allow ansistrings, the shortstring version is
  306. OS dependent }
  307. var
  308. s : shortstring;
  309. begin
  310. getdir(drivenr,s);
  311. dir:=s;
  312. end;
  313. {$ifopt R+}
  314. {$define RangeCheckWasOn}
  315. {$R-}
  316. {$endif opt R+}
  317. {$ifopt I+}
  318. {$define IOCheckWasOn}
  319. {$I-}
  320. {$endif opt I+}
  321. {$ifopt Q+}
  322. {$define OverflowCheckWasOn}
  323. {$Q-}
  324. {$endif opt Q+}
  325. {*****************************************************************************
  326. Miscellaneous
  327. *****************************************************************************}
  328. procedure fpc_rangeerror;[public,alias:'FPC_RANGEERROR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  329. begin
  330. HandleErrorFrame(201,get_frame);
  331. end;
  332. procedure fpc_overflow;[public,alias:'FPC_OVERFLOW']; {$ifdef hascompilerproc} compilerproc; {$endif}
  333. begin
  334. HandleErrorFrame(215,get_frame);
  335. end;
  336. procedure fpc_iocheck(addr : longint);[saveregisters,public,alias:'FPC_IOCHECK']; {$ifdef hascompilerproc} compilerproc; {$endif}
  337. var
  338. l : longint;
  339. begin
  340. if InOutRes<>0 then
  341. begin
  342. l:=InOutRes;
  343. InOutRes:=0;
  344. HandleErrorFrame(l,get_frame);
  345. end;
  346. end;
  347. Function IOResult:Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  348. Begin
  349. IOResult:=InOutRes;
  350. InOutRes:=0;
  351. End;
  352. {*****************************************************************************
  353. Stack check code
  354. *****************************************************************************}
  355. {$IFNDEF NO_GENERIC_STACK_CHECK}
  356. {$IFOPT S+}
  357. {$DEFINE STACKCHECK}
  358. {$ENDIF}
  359. {$S-}
  360. procedure fpc_stackcheck(stack_size:Cardinal);[saveregisters,public,alias:'FPC_STACKCHECK'];
  361. var
  362. c : cardinal;
  363. begin
  364. { Avoid recursive calls when called from the exit routines }
  365. if StackError then
  366. exit;
  367. c := cardinal(Sptr) - stack_size - STACK_MARGIN;
  368. if (c <= StackBottom) then
  369. begin
  370. StackError:=true;
  371. HandleError(202);
  372. end;
  373. end;
  374. {$IFDEF STACKCHECK}
  375. {$S+}
  376. {$ENDIF}
  377. {$UNDEF STACKCHECK}
  378. {$ENDIF NO_GENERIC_STACK_CHECK}
  379. {*****************************************************************************
  380. Initialization / Finalization
  381. *****************************************************************************}
  382. const
  383. maxunits=1024; { See also files.pas of the compiler source }
  384. type
  385. TInitFinalRec=record
  386. InitProc,
  387. FinalProc : TProcedure;
  388. end;
  389. TInitFinalTable=record
  390. TableCount,
  391. InitCount : longint;
  392. Procs : array[1..maxunits] of TInitFinalRec;
  393. end;
  394. var
  395. InitFinalTable : TInitFinalTable;external name 'INITFINAL';
  396. procedure fpc_InitializeUnits;[public,alias:'FPC_INITIALIZEUNITS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  397. var
  398. i : longint;
  399. begin
  400. with InitFinalTable do
  401. begin
  402. for i:=1to TableCount do
  403. begin
  404. if assigned(Procs[i].InitProc) then
  405. Procs[i].InitProc();
  406. InitCount:=i;
  407. end;
  408. end;
  409. end;
  410. procedure FinalizeUnits;[public,alias:'FPC_FINALIZEUNITS'];
  411. begin
  412. with InitFinalTable do
  413. begin
  414. while (InitCount>0) do
  415. begin
  416. // we've to decrement the cound before calling the final. code
  417. // else a halt in the final. code leads to a endless loop
  418. dec(InitCount);
  419. if assigned(Procs[InitCount+1].FinalProc) then
  420. Procs[InitCount+1].FinalProc();
  421. end;
  422. end;
  423. end;
  424. {*****************************************************************************
  425. Error / Exit / ExitProc
  426. *****************************************************************************}
  427. Procedure system_exit;forward;
  428. Procedure InternalExit;
  429. var
  430. current_exit : Procedure;
  431. Begin
  432. while exitProc<>nil Do
  433. Begin
  434. InOutRes:=0;
  435. current_exit:=tProcedure(exitProc);
  436. exitProc:=nil;
  437. current_exit();
  438. End;
  439. { Finalize units }
  440. FinalizeUnits;
  441. { Show runtime error and exit }
  442. If erroraddr<>nil Then
  443. Begin
  444. Writeln(stdout,'Runtime error ',Errorcode,' at 0x',hexstr(Longint(Erroraddr),8));
  445. { to get a nice symify }
  446. Writeln(stdout,BackTraceStrFunc(Longint(Erroraddr)));
  447. dump_stack(stdout,ErrorBase);
  448. Writeln(stdout,'');
  449. End;
  450. End;
  451. Procedure do_exit;[Public,Alias:'FPC_DO_EXIT'];
  452. begin
  453. InternalExit;
  454. System_exit;
  455. end;
  456. Procedure lib_exit;saveregisters;[Public,Alias:'FPC_LIB_EXIT'];
  457. begin
  458. InternalExit;
  459. end;
  460. Procedure Halt(ErrNum: Byte);
  461. Begin
  462. ExitCode:=Errnum;
  463. Do_Exit;
  464. end;
  465. function SysBackTraceStr (Addr: longint): ShortString;
  466. begin
  467. SysBackTraceStr:=' 0x'+HexStr(addr,8);
  468. end;
  469. Procedure HandleErrorAddrFrame (Errno : longint;addr,frame : longint);[public,alias:'FPC_BREAK_ERROR'];
  470. begin
  471. If pointer(ErrorProc)<>Nil then
  472. ErrorProc(Errno,pointer(addr),pointer(frame));
  473. errorcode:=word(Errno);
  474. exitcode:=word(Errno);
  475. erroraddr:=pointer(addr);
  476. errorbase:=frame;
  477. halt(errorcode);
  478. end;
  479. Procedure HandleErrorFrame (Errno : longint;frame : longint);
  480. {
  481. Procedure to handle internal errors, i.e. not user-invoked errors
  482. Internal function should ALWAYS call HandleError instead of RunError.
  483. Can be used for exception handlers to specify the frame
  484. }
  485. begin
  486. HandleErrorAddrFrame(Errno,get_caller_addr(frame),get_caller_frame(frame));
  487. end;
  488. Procedure HandleError (Errno : longint);[public,alias : 'FPC_HANDLEERROR'];
  489. {
  490. Procedure to handle internal errors, i.e. not user-invoked errors
  491. Internal function should ALWAYS call HandleError instead of RunError.
  492. }
  493. begin
  494. HandleErrorFrame(Errno,get_frame);
  495. end;
  496. procedure runerror(w : word);[alias: 'FPC_RUNERROR'];
  497. begin
  498. errorcode:=w;
  499. exitcode:=w;
  500. erroraddr:=pointer(get_caller_addr(get_frame));
  501. errorbase:=get_caller_frame(get_frame);
  502. halt(errorcode);
  503. end;
  504. Procedure RunError;{$ifdef SYSTEMINLINE}inline;{$endif}
  505. Begin
  506. RunError (0);
  507. End;
  508. Procedure Halt;{$ifdef SYSTEMINLINE}inline;{$endif}
  509. Begin
  510. Halt(0);
  511. End;
  512. function do_isdevice(handle:longint):boolean;forward;
  513. Procedure dump_stack(var f : text;bp : Longint);
  514. var
  515. i, prevbp : Longint;
  516. is_dev : boolean;
  517. caller_addr : longint;
  518. Begin
  519. prevbp:=bp-1;
  520. i:=0;
  521. is_dev:=do_isdevice(textrec(f).Handle);
  522. while bp > prevbp Do
  523. Begin
  524. caller_addr := get_caller_addr(bp);
  525. if caller_addr <> 0 then
  526. Writeln(f,BackTraceStrFunc(caller_addr));
  527. Inc(i);
  528. If ((i>max_frame_dump) and is_dev) or (i>256) Then
  529. exit;
  530. prevbp:=bp;
  531. bp:=get_caller_frame(bp);
  532. End;
  533. End;
  534. Type
  535. PExitProcInfo = ^TExitProcInfo;
  536. TExitProcInfo = Record
  537. Next : PExitProcInfo;
  538. SaveExit : Pointer;
  539. Proc : TProcedure;
  540. End;
  541. const
  542. ExitProcList: PExitProcInfo = nil;
  543. Procedure DoExitProc;
  544. var
  545. P : PExitProcInfo;
  546. Proc : TProcedure;
  547. Begin
  548. P:=ExitProcList;
  549. ExitProcList:=P^.Next;
  550. ExitProc:=P^.SaveExit;
  551. Proc:=P^.Proc;
  552. DisPose(P);
  553. Proc();
  554. End;
  555. Procedure AddExitProc(Proc: TProcedure);
  556. var
  557. P : PExitProcInfo;
  558. Begin
  559. New(P);
  560. P^.Next:=ExitProcList;
  561. P^.SaveExit:=ExitProc;
  562. P^.Proc:=Proc;
  563. ExitProcList:=P;
  564. ExitProc:=@DoExitProc;
  565. End;
  566. {*****************************************************************************
  567. Abstract/Assert support.
  568. *****************************************************************************}
  569. procedure AbstractError;[public,alias : 'FPC_ABSTRACTERROR'];
  570. begin
  571. If pointer(AbstractErrorProc)<>nil then
  572. AbstractErrorProc();
  573. HandleErrorFrame(211,get_frame);
  574. end;
  575. {$ifdef hascompilerproc}
  576. { alias for internal usage in the compiler }
  577. procedure fpc_AbstractErrorIntern; compilerproc; external name 'FPC_ABSTRACTERROR';
  578. {$endif hascompilerproc}
  579. Procedure fpc_assert(Const Msg,FName:Shortstring;LineNo,ErrorAddr:Longint); [SaveRegisters,Public,Alias : 'FPC_ASSERT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  580. begin
  581. if pointer(AssertErrorProc)<>nil then
  582. AssertErrorProc(Msg,FName,LineNo,ErrorAddr)
  583. else
  584. HandleErrorFrame(227,get_frame);
  585. end;
  586. Procedure SysAssert(Const Msg,FName:Shortstring;LineNo,ErrorAddr:Longint);
  587. begin
  588. If msg='' then
  589. write(stderr,'Assertion failed')
  590. else
  591. write(stderr,msg);
  592. Writeln(stderr,' (',FName,', line ',LineNo,').');
  593. Writeln(stderr,'');
  594. Halt(227);
  595. end;
  596. {*****************************************************************************
  597. SetJmp/LongJmp support.
  598. *****************************************************************************}
  599. {$i setjump.inc}
  600. {$ifdef IOCheckWasOn}
  601. {$I+}
  602. {$endif}
  603. {$ifdef RangeCheckWasOn}
  604. {$R+}
  605. {$endif}
  606. {$ifdef OverflowCheckWasOn}
  607. {$Q+}
  608. {$endif}
  609. {
  610. $Log$
  611. Revision 1.38 2002-12-07 14:36:33 carl
  612. - avoid warnings (add typecast)
  613. Revision 1.37 2002/11/18 18:33:51 peter
  614. * Swap(QWord) constant support
  615. Revision 1.36 2002/10/14 19:39:17 peter
  616. * threads unit added for thread support
  617. Revision 1.35 2002/09/18 18:32:01 carl
  618. * assert now halts with exitcode 227 (as Delphi does)
  619. Revision 1.34 2002/09/07 15:07:46 peter
  620. * old logs removed and tabs fixed
  621. Revision 1.33 2002/08/19 19:34:02 peter
  622. * SYSTEMINLINE define that will add inline directives for small
  623. functions and wrappers. This will be defined automaticly when
  624. the compiler defines the HASINLINE directive
  625. Revision 1.32 2002/07/28 20:43:48 florian
  626. * several fixes for linux/powerpc
  627. * several fixes to MT
  628. Revision 1.31 2002/07/26 22:46:06 florian
  629. * interface of system unit for Linux/PowerPC compiles
  630. Revision 1.30 2002/07/26 16:42:00 florian
  631. * endian directive for PowerPC fixed
  632. Revision 1.29 2002/07/04 20:40:09 florian
  633. + some x86-64 support added
  634. Revision 1.28 2002/04/21 15:51:50 carl
  635. * StackError is now a typed constant
  636. + $S can be used under unix
  637. Revision 1.27 2002/04/15 19:38:40 peter
  638. * stackcheck protected against infinite recursive after stack error
  639. * stackcheck requires saveregisters, because it can be called from
  640. iocheck and then will destroy the result of the original function
  641. Revision 1.26 2002/04/15 18:51:20 carl
  642. + generic stack checking can be overriden
  643. Revision 1.25 2002/04/12 17:37:36 carl
  644. + generic stack checking
  645. }