system.inc 17 KB

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