system.inc 17 KB

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