system.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  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. { Random / Randomize constants }
  28. OldRandSeed : Cardinal = 0;
  29. InitialSeed : Boolean = TRUE;
  30. Seed2 : Cardinal = 0;
  31. Seed3 : Cardinal = 0;
  32. { For Error Handling.}
  33. ErrorBase : Longint = 0;
  34. { Used by the ansistrings and maybe also other things in the future }
  35. var
  36. emptychar : char;public name 'FPC_EMPTYCHAR';
  37. {****************************************************************************
  38. Routines which have compiler magic
  39. ****************************************************************************}
  40. {$I innr.inc}
  41. Function lo(i : Integer) : byte; [INTERNPROC: In_lo_Word];
  42. Function lo(w : Word) : byte; [INTERNPROC: In_lo_Word];
  43. Function lo(l : Longint) : Word; [INTERNPROC: In_lo_long];
  44. Function lo(l : DWord) : Word; [INTERNPROC: In_lo_long];
  45. Function hi(i : Integer) : byte; [INTERNPROC: In_hi_Word];
  46. Function hi(w : Word) : byte; [INTERNPROC: In_hi_Word];
  47. Function hi(l : Longint) : Word; [INTERNPROC: In_hi_long];
  48. Function hi(l : DWord) : Word; [INTERNPROC: In_hi_long];
  49. Function lo(q : QWord) : DWord; [INTERNPROC: In_lo_qword];
  50. Function lo(i : Int64) : DWord; [INTERNPROC: In_lo_qword];
  51. Function hi(q : QWord) : DWord; [INTERNPROC: In_hi_qword];
  52. Function hi(i : Int64) : DWord; [INTERNPROC: In_hi_qword];
  53. Function chr(b : byte) : Char; [INTERNPROC: In_chr_byte];
  54. {$ifndef INTERNLENGTH}
  55. Function Length(s : string) : byte; [INTERNPROC: In_Length_string];
  56. Function Length(c : char) : byte; [INTERNPROC: In_Length_string];
  57. {$endif INTERNLENGTH}
  58. Procedure Reset(var f : TypedFile); [INTERNPROC: In_Reset_TypedFile];
  59. Procedure Rewrite(var f : TypedFile); [INTERNPROC: In_Rewrite_TypedFile];
  60. {****************************************************************************
  61. Include processor specific routines
  62. ****************************************************************************}
  63. {$IFDEF I386}
  64. {$IFNDEF ENDIAN_LITTLE}
  65. {$DEFINE ENDIAN_LITTLE}
  66. {$ENDIF}
  67. {$IFDEF M68K}
  68. {$Error Can't determine processor type !}
  69. {$ENDIF}
  70. {$I i386.inc} { Case dependent, don't change }
  71. {$ELSE}
  72. {$IFDEF M68K}
  73. {$IFNDEF ENDIAN_BIG}
  74. {$DEFINE ENDIAN_BIG}
  75. {$ENDIF}
  76. {$I m68k.inc} { Case dependent, don't change }
  77. {$ELSE}
  78. {$Error Can't determine processor type !}
  79. {$ENDIF}
  80. {$ENDIF}
  81. { Include generic pascal only routines which are not defined in the processor
  82. specific include file }
  83. {$I generic.inc}
  84. {****************************************************************************
  85. Set Handling
  86. ****************************************************************************}
  87. { Include set support which is processor specific}
  88. {$I set.inc}
  89. { Include generic pascal routines for sets if the processor }
  90. { specific routines are not available. }
  91. {$I genset.inc}
  92. {****************************************************************************
  93. Math Routines
  94. ****************************************************************************}
  95. function Hi(b : byte): byte;
  96. begin
  97. Hi := b shr 4
  98. end;
  99. function Lo(b : byte): byte;
  100. begin
  101. Lo := b and $0f
  102. end;
  103. Function swap (X : Word) : Word;[internconst:in_const_swap_word];
  104. Begin
  105. swap:=(X and $ff) shl 8 + (X shr 8)
  106. End;
  107. Function Swap (X : Integer) : Integer;[internconst:in_const_swap_word];
  108. Begin
  109. swap:=(X and $ff) shl 8 + (X shr 8)
  110. End;
  111. Function swap (X : Longint) : Longint;[internconst:in_const_swap_long];
  112. Begin
  113. Swap:=(X and $ffff) shl 16 + (X shr 16)
  114. End;
  115. Function Swap (X : Cardinal) : Cardinal;[internconst:in_const_swap_long];
  116. Begin
  117. Swap:=(X and $ffff) shl 16 + (X shr 16)
  118. End;
  119. Function Swap (X : QWord) : QWord;
  120. Begin
  121. Swap:=(X and $ffffffff) shl 32 + (X shr 32);
  122. End;
  123. Function swap (X : Int64) : Int64;
  124. Begin
  125. Swap:=(X and $ffffffff) shl 32 + (X shr 32);
  126. End;
  127. { Include processor specific routines }
  128. {$I math.inc}
  129. {****************************************************************************
  130. Subroutines for String handling
  131. ****************************************************************************}
  132. { Needs to be before RTTI handling }
  133. {$i sstrings.inc}
  134. { requires sstrings.inc for initval }
  135. {$I int64.inc}
  136. {Requires int64.inc, since that contains the VAL functions for int64 and qword}
  137. {$i astrings.inc}
  138. {$ifdef HASWIDESTRING}
  139. {$i wstrings.inc}
  140. {$endif HASWIDESTRING}
  141. {*****************************************************************************
  142. Dynamic Array support
  143. *****************************************************************************}
  144. {$i dynarr.inc}
  145. {*****************************************************************************
  146. Object Pascal support
  147. *****************************************************************************}
  148. {$i objpas.inc}
  149. {****************************************************************************
  150. Run-Time Type Information (RTTI)
  151. ****************************************************************************}
  152. {$i rtti.inc}
  153. {****************************************************************************
  154. Random function routines
  155. This implements a very long cycle random number generator by combining
  156. three independant generators. The technique was described in the March
  157. 1987 issue of Byte.
  158. Taken and modified with permission from the PCQ Pascal rtl code.
  159. ****************************************************************************}
  160. {$R-}
  161. {$Q-}
  162. Procedure NewSeed;Forward;
  163. Function Random : Extended;
  164. begin
  165. if (InitialSeed) OR (RandSeed <> OldRandSeed) then
  166. Begin
  167. { This is a pretty complicated affair }
  168. { Initially we must call NewSeed when RandSeed is initalized }
  169. { We must also call NewSeed each time RandSeed is reinitialized }
  170. { DO NOT CHANGE THE ORDER OF DECLARATIONS IN THIS BLOCK }
  171. { UNLESS YOU WANT RANDON TO CRASH OF COURSE (CEC) }
  172. InitialSeed:=FALSE;
  173. OldRandSeed:=RandSeed;
  174. NewSeed;
  175. end;
  176. Inc(RandSeed);
  177. RandSeed := (RandSeed * 706) mod 500009;
  178. OldRandSeed:=RandSeed;
  179. INC(Seed2);
  180. Seed2 := (Seed2 * 774) MOD 600011;
  181. INC(Seed3);
  182. Seed3 := (Seed3 * 871) MOD 765241;
  183. Random :=
  184. frac(RandSeed/500009.0 +
  185. Seed2/600011.0 +
  186. Seed3/765241.0);
  187. end;
  188. Function internRandom(l : Cardinal) : Cardinal;
  189. begin
  190. if (InitialSeed) OR (RandSeed <> OldRandSeed) then
  191. Begin
  192. { This is a pretty complicated affair }
  193. { Initially we must call NewSeed when RandSeed is initalized }
  194. { We must also call NewSeed each time RandSeed is reinitialized }
  195. { DO NOT CHANGE THE ORDER OF DECLARATIONS IN THIS BLOCK }
  196. { UNLESS YOU WANT RANDOM TO CRASH OF COURSE (CEC) }
  197. InitialSeed:=FALSE;
  198. OldRandSeed:=RandSeed;
  199. NewSeed;
  200. end;
  201. Inc(RandSeed);
  202. RandSeed := (RandSeed * 998) mod 1000003;
  203. OldRandSeed:=RandSeed;
  204. if l<>0 then
  205. begin
  206. internRandom := RandSeed mod l;
  207. end
  208. else internRandom:=0;
  209. end;
  210. function random(l:cardinal): cardinal;
  211. begin
  212. random := trunc(random()*l);
  213. end;
  214. function random(l:longint): longint;
  215. begin
  216. random := trunc(random()*l);
  217. end;
  218. Procedure NewSeed;
  219. begin
  220. randseed := randseed mod 1000003;
  221. Seed2 := (internRandom(65000) * internRandom(65000)) mod 600011;
  222. Seed3 := (internRandom(65000) * internRandom(65000)) mod 765241;
  223. end;
  224. {****************************************************************************
  225. Memory Management
  226. ****************************************************************************}
  227. Function Ptr(sel,off : Longint) : farpointer;[internconst:in_const_ptr];
  228. Begin
  229. ptr:=farpointer((sel shl 4)+off);
  230. End;
  231. Function CSeg : Word;
  232. Begin
  233. Cseg:=0;
  234. End;
  235. Function DSeg : Word;
  236. Begin
  237. Dseg:=0;
  238. End;
  239. Function SSeg : Word;
  240. Begin
  241. Sseg:=0;
  242. End;
  243. {*****************************************************************************
  244. Directory support.
  245. *****************************************************************************}
  246. Procedure getdir(drivenr:byte;Var dir:ansistring);
  247. { this is needed to also allow ansistrings, the shortstring version is
  248. OS dependent }
  249. var
  250. s : shortstring;
  251. begin
  252. getdir(drivenr,s);
  253. dir:=s;
  254. end;
  255. {$ifopt R+}
  256. {$define RangeCheckWasOn}
  257. {$R-}
  258. {$endif opt R+}
  259. {$ifopt I+}
  260. {$define IOCheckWasOn}
  261. {$I-}
  262. {$endif opt I+}
  263. {$ifopt Q+}
  264. {$define OverflowCheckWasOn}
  265. {$Q-}
  266. {$endif opt Q+}
  267. {*****************************************************************************
  268. Miscellaneous
  269. *****************************************************************************}
  270. procedure int_rangeerror;[public,alias:'FPC_RANGEERROR'];
  271. begin
  272. HandleErrorFrame(201,get_frame);
  273. end;
  274. procedure int_overflow;[public,alias:'FPC_OVERFLOW'];
  275. begin
  276. HandleErrorFrame(215,get_frame);
  277. end;
  278. procedure int_iocheck(addr : longint);[saveregisters,public,alias:'FPC_IOCHECK'];
  279. var
  280. l : longint;
  281. begin
  282. if InOutRes<>0 then
  283. begin
  284. l:=InOutRes;
  285. InOutRes:=0;
  286. HandleErrorFrame(l,get_frame);
  287. end;
  288. end;
  289. Function IOResult:Word;
  290. Begin
  291. IOResult:=InOutRes;
  292. InOutRes:=0;
  293. End;
  294. procedure fillchar(var x;count : longint;value : boolean);
  295. begin
  296. fillchar(x,count,byte(value));
  297. end;
  298. procedure fillchar(var x;count : longint;value : char);
  299. begin
  300. fillchar(x,count,byte(value));
  301. end;
  302. {*****************************************************************************
  303. Initialization / Finalization
  304. *****************************************************************************}
  305. const
  306. maxunits=1024; { See also files.pas of the compiler source }
  307. type
  308. TInitFinalRec=record
  309. InitProc,
  310. FinalProc : TProcedure;
  311. end;
  312. TInitFinalTable=record
  313. TableCount,
  314. InitCount : longint;
  315. Procs : array[1..maxunits] of TInitFinalRec;
  316. end;
  317. var
  318. InitFinalTable : TInitFinalTable;external name 'INITFINAL';
  319. procedure InitializeUnits;[public,alias:'FPC_INITIALIZEUNITS'];
  320. var
  321. i : longint;
  322. begin
  323. with InitFinalTable do
  324. begin
  325. for i:=1to TableCount do
  326. begin
  327. if assigned(Procs[i].InitProc) then
  328. Procs[i].InitProc();
  329. InitCount:=i;
  330. end;
  331. end;
  332. end;
  333. procedure FinalizeUnits;[public,alias:'FPC_FINALIZEUNITS'];
  334. begin
  335. with InitFinalTable do
  336. begin
  337. while (InitCount>0) do
  338. begin
  339. // we've to decrement the cound before calling the final. code
  340. // else a halt in the final. code leads to a endless loop
  341. dec(InitCount);
  342. if assigned(Procs[InitCount+1].FinalProc) then
  343. Procs[InitCount+1].FinalProc();
  344. end;
  345. end;
  346. end;
  347. {*****************************************************************************
  348. Error / Exit / ExitProc
  349. *****************************************************************************}
  350. Procedure system_exit;forward;
  351. Procedure InternalExit;
  352. var
  353. current_exit : Procedure;
  354. Begin
  355. while exitProc<>nil Do
  356. Begin
  357. InOutRes:=0;
  358. current_exit:=tProcedure(exitProc);
  359. exitProc:=nil;
  360. current_exit();
  361. End;
  362. { Finalize units }
  363. FinalizeUnits;
  364. { Show runtime error and exit }
  365. If erroraddr<>nil Then
  366. Begin
  367. Writeln(stdout,'Runtime error ',Errorcode,' at 0x',hexstr(Longint(Erroraddr),8));
  368. { to get a nice symify }
  369. Writeln(stdout,BackTraceStrFunc(Longint(Erroraddr)));
  370. dump_stack(stdout,ErrorBase);
  371. Writeln(stdout,'');
  372. End;
  373. End;
  374. Procedure do_exit;[Public,Alias:'FPC_DO_EXIT'];
  375. begin
  376. InternalExit;
  377. System_exit;
  378. end;
  379. Procedure lib_exit;saveregisters;[Public,Alias:'FPC_LIB_EXIT'];
  380. begin
  381. InternalExit;
  382. end;
  383. Procedure Halt(ErrNum: Byte);
  384. Begin
  385. ExitCode:=Errnum;
  386. Do_Exit;
  387. end;
  388. function SysBackTraceStr (Addr: longint): ShortString;
  389. begin
  390. SysBackTraceStr:=' 0x'+HexStr(addr,8);
  391. end;
  392. Procedure HandleErrorAddrFrame (Errno : longint;addr,frame : longint);[public,alias:'FPC_BREAK_ERROR'];
  393. begin
  394. If pointer(ErrorProc)<>Nil then
  395. ErrorProc(Errno,pointer(addr),pointer(frame));
  396. errorcode:=Errno;
  397. exitcode:=Errno;
  398. erroraddr:=pointer(addr);
  399. errorbase:=frame;
  400. halt(errorcode);
  401. end;
  402. Procedure HandleErrorFrame (Errno : longint;frame : longint);
  403. {
  404. Procedure to handle internal errors, i.e. not user-invoked errors
  405. Internal function should ALWAYS call HandleError instead of RunError.
  406. Can be used for exception handlers to specify the frame
  407. }
  408. begin
  409. HandleErrorAddrFrame(Errno,get_caller_addr(frame),get_caller_frame(frame));
  410. end;
  411. Procedure HandleError (Errno : longint);[public,alias : 'FPC_HANDLEERROR'];
  412. {
  413. Procedure to handle internal errors, i.e. not user-invoked errors
  414. Internal function should ALWAYS call HandleError instead of RunError.
  415. }
  416. begin
  417. HandleErrorFrame(Errno,get_frame);
  418. end;
  419. procedure runerror(w : word);[alias: 'FPC_RUNERROR'];
  420. begin
  421. errorcode:=w;
  422. exitcode:=w;
  423. erroraddr:=pointer(get_caller_addr(get_frame));
  424. errorbase:=get_caller_frame(get_frame);
  425. halt(errorcode);
  426. end;
  427. Procedure RunError;
  428. Begin
  429. RunError (0);
  430. End;
  431. Procedure Halt;
  432. Begin
  433. Halt(0);
  434. End;
  435. function do_isdevice(handle:longint):boolean;forward;
  436. Procedure dump_stack(var f : text;bp : Longint);
  437. var
  438. i, prevbp : Longint;
  439. is_dev : boolean;
  440. Begin
  441. prevbp:=bp-1;
  442. i:=0;
  443. is_dev:=do_isdevice(textrec(f).Handle);
  444. while bp > prevbp Do
  445. Begin
  446. Writeln(f,BackTraceStrFunc(get_caller_addr(bp)));
  447. Inc(i);
  448. If ((i>max_frame_dump) and is_dev) or (i>256) Then
  449. exit;
  450. prevbp:=bp;
  451. bp:=get_caller_frame(bp);
  452. End;
  453. End;
  454. Type
  455. PExitProcInfo = ^TExitProcInfo;
  456. TExitProcInfo = Record
  457. Next : PExitProcInfo;
  458. SaveExit : Pointer;
  459. Proc : TProcedure;
  460. End;
  461. const
  462. ExitProcList: PExitProcInfo = nil;
  463. Procedure DoExitProc;
  464. var
  465. P : PExitProcInfo;
  466. Proc : TProcedure;
  467. Begin
  468. P:=ExitProcList;
  469. ExitProcList:=P^.Next;
  470. ExitProc:=P^.SaveExit;
  471. Proc:=P^.Proc;
  472. DisPose(P);
  473. Proc();
  474. End;
  475. Procedure AddExitProc(Proc: TProcedure);
  476. var
  477. P : PExitProcInfo;
  478. Begin
  479. New(P);
  480. P^.Next:=ExitProcList;
  481. P^.SaveExit:=ExitProc;
  482. P^.Proc:=Proc;
  483. ExitProcList:=P;
  484. ExitProc:=@DoExitProc;
  485. End;
  486. {*****************************************************************************
  487. Abstract/Assert support.
  488. *****************************************************************************}
  489. procedure AbstractError;[public,alias : 'FPC_ABSTRACTERROR'];
  490. begin
  491. If pointer(AbstractErrorProc)<>nil then
  492. AbstractErrorProc();
  493. HandleErrorFrame(211,get_frame);
  494. end;
  495. Procedure int_assert(Const Msg,FName:Shortstring;LineNo,ErrorAddr:Longint); [SaveRegisters,Public,Alias : 'FPC_ASSERT'];
  496. begin
  497. if pointer(AssertErrorProc)<>nil then
  498. AssertErrorProc(Msg,FName,LineNo,ErrorAddr)
  499. else
  500. HandleErrorFrame(227,get_frame);
  501. end;
  502. Procedure SysAssert(Const Msg,FName:Shortstring;LineNo,ErrorAddr:Longint);
  503. begin
  504. If msg='' then
  505. write(stderr,'Assertion failed')
  506. else
  507. write(stderr,msg);
  508. Writeln(stderr,' (',FName,', line ',LineNo,').');
  509. Writeln(stderr,'');
  510. end;
  511. {*****************************************************************************
  512. SetJmp/LongJmp support.
  513. *****************************************************************************}
  514. {$i setjump.inc}
  515. {$ifdef IOCheckWasOn}
  516. {$I+}
  517. {$endif}
  518. {$ifdef RangeCheckWasOn}
  519. {$R+}
  520. {$endif}
  521. {$ifdef OverflowCheckWasOn}
  522. {$Q+}
  523. {$endif}
  524. {
  525. $Log$
  526. Revision 1.17 2001-07-09 21:15:41 peter
  527. * Length made internal
  528. * Add array support for Length
  529. Revision 1.16 2001/07/08 21:00:18 peter
  530. * various widestring updates, it works now mostly without charset
  531. mapping supported
  532. Revision 1.15 2001/06/13 18:32:05 peter
  533. * big endian updates (merged)
  534. Revision 1.14 2001/06/03 15:15:58 peter
  535. * lib_exit added
  536. Revision 1.13 2001/05/09 19:57:07 peter
  537. *** empty log message ***
  538. Revision 1.12 2001/04/13 18:06:28 peter
  539. * removed rtllite define
  540. Revision 1.11 2000/12/16 15:56:19 jonas
  541. - removed all ifdef cardinalmulfix code
  542. Revision 1.10 2000/11/13 14:47:46 jonas
  543. * support for range checking when converting from 64bit to something
  544. smaller (32bit, 16bit, 8bit)
  545. * fixed range checking between longint/cardinal and for array indexing
  546. with cardinal (values > $7fffffff were considered negative)
  547. Revision 1.9 2000/11/11 16:12:01 peter
  548. * ptr returns farpointer
  549. Revision 1.8 2000/11/06 21:35:59 peter
  550. * removed some warnings
  551. Revision 1.7 2000/11/04 17:52:46 florian
  552. * fixed linker errors
  553. Revision 1.6 2000/10/13 12:04:03 peter
  554. * FPC_BREAK_ERROR added
  555. Revision 1.5 2000/08/13 17:55:14 michael
  556. + Added some delphi compatibility types
  557. Revision 1.4 2000/08/09 19:31:18 marco
  558. * fixes for val(int64 or qword) to ansistring
  559. Revision 1.3 2000/07/14 10:33:10 michael
  560. + Conditionals fixed
  561. Revision 1.2 2000/07/13 11:33:45 michael
  562. + removed logs
  563. }