system.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  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. PLongint = ^Longint;
  27. PByte = ^Byte;
  28. const
  29. { Random / Randomize constants }
  30. OldRandSeed : Cardinal = 0;
  31. InitialSeed : Boolean = TRUE;
  32. Seed2 : Cardinal = 0;
  33. Seed3 : Cardinal = 0;
  34. { For Error Handling.}
  35. ErrorBase : Longint = 0;
  36. { Used by the ansistrings and maybe also other things in the future }
  37. var
  38. emptychar : char;public name 'FPC_EMPTYCHAR';
  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. {$ifdef INT64}
  52. Function lo(q : QWord) : DWord; [INTERNPROC: In_lo_qword];
  53. Function lo(i : Int64) : DWord; [INTERNPROC: In_lo_qword];
  54. Function hi(q : QWord) : DWord; [INTERNPROC: In_hi_qword];
  55. Function hi(i : Int64) : DWord; [INTERNPROC: In_hi_qword];
  56. {$endif}
  57. Function chr(b : byte) : Char; [INTERNPROC: In_chr_byte];
  58. Function Length(s : string) : byte; [INTERNPROC: In_Length_string];
  59. Function Length(c : char) : byte; [INTERNPROC: In_Length_string];
  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 M68K}
  67. {$Error Can't determine processor type !}
  68. {$ENDIF}
  69. {$I i386.inc} { Case dependent, don't change }
  70. {$ELSE}
  71. {$IFDEF M68K}
  72. {$I m68k.inc} { Case dependent, don't change }
  73. {$ELSE}
  74. {$Error Can't determine processor type !}
  75. {$ENDIF}
  76. {$ENDIF}
  77. {****************************************************************************
  78. Set Handling
  79. ****************************************************************************}
  80. { Include set support which is processor specific}
  81. {$I set.inc}
  82. {****************************************************************************
  83. Subroutines for String handling
  84. ****************************************************************************}
  85. { Needs to be before RTTI handling }
  86. {$i sstrings.inc}
  87. {$i astrings.inc}
  88. {$ifdef haswidechar}
  89. {$i wstrings.inc}
  90. {$endif haswidechar}
  91. {****************************************************************************
  92. Run-Time Type Information (RTTI)
  93. ****************************************************************************}
  94. {$i rtti.inc}
  95. {****************************************************************************
  96. Math Routines
  97. ****************************************************************************}
  98. {$ifndef RTLLITE}
  99. function Hi(b : byte): byte;
  100. begin
  101. Hi := b shr 4
  102. end;
  103. function Lo(b : byte): byte;
  104. begin
  105. Lo := b and $0f
  106. end;
  107. Function swap (X : Word) : Word;[internconst:in_const_swap_word];
  108. Begin
  109. swap:=(X and $ff) shl 8 + (X shr 8)
  110. End;
  111. Function Swap (X : Integer) : Integer;[internconst:in_const_swap_word];
  112. Begin
  113. swap:=(X and $ff) shl 8 + (X shr 8)
  114. End;
  115. Function swap (X : Longint) : Longint;[internconst:in_const_swap_long];
  116. Begin
  117. Swap:=(X and $ffff) shl 16 + (X shr 16)
  118. End;
  119. Function Swap (X : Cardinal) : Cardinal;[internconst:in_const_swap_long];
  120. Begin
  121. Swap:=(X and $ffff) shl 16 + (X shr 16)
  122. End;
  123. {$ifdef INT64}
  124. Function Swap (X : QWord) : QWord;
  125. Begin
  126. Swap:=(X and $ffffffff) shl 32 + (X shr 32);
  127. End;
  128. Function swap (X : Int64) : Int64;
  129. Begin
  130. Swap:=(X and $ffffffff) shl 32 + (X shr 32);
  131. End;
  132. {$endif}
  133. {$endif RTLLITE}
  134. {****************************************************************************
  135. Random function routines
  136. This implements a very long cycle random number generator by combining
  137. three independant generators. The technique was described in the March
  138. 1987 issue of Byte.
  139. Taken and modified with permission from the PCQ Pascal rtl code.
  140. ****************************************************************************}
  141. {$R-}
  142. {$Q-}
  143. Procedure NewSeed;Forward;
  144. Function Random : Extended;
  145. begin
  146. if (InitialSeed) OR (RandSeed <> OldRandSeed) then
  147. Begin
  148. { This is a pretty complicated affair }
  149. { Initially we must call NewSeed when RandSeed is initalized }
  150. { We must also call NewSeed each time RandSeed is reinitialized }
  151. { DO NOT CHANGE THE ORDER OF DECLARATIONS IN THIS BLOCK }
  152. { UNLESS YOU WANT RANDON TO CRASH OF COURSE (CEC) }
  153. InitialSeed:=FALSE;
  154. OldRandSeed:=RandSeed;
  155. NewSeed;
  156. end;
  157. Inc(RandSeed);
  158. RandSeed := (RandSeed * 706) mod 500009;
  159. OldRandSeed:=RandSeed;
  160. INC(Seed2);
  161. Seed2 := (Seed2 * 774) MOD 600011;
  162. INC(Seed3);
  163. Seed3 := (Seed3 * 871) MOD 765241;
  164. Random :=
  165. frac(RandSeed/500009.0 +
  166. Seed2/600011.0 +
  167. Seed3/765241.0);
  168. end;
  169. Function internRandom(l : Cardinal) : Cardinal;
  170. begin
  171. if (InitialSeed) OR (RandSeed <> OldRandSeed) then
  172. Begin
  173. { This is a pretty complicated affair }
  174. { Initially we must call NewSeed when RandSeed is initalized }
  175. { We must also call NewSeed each time RandSeed is reinitialized }
  176. { DO NOT CHANGE THE ORDER OF DECLARATIONS IN THIS BLOCK }
  177. { UNLESS YOU WANT RANDOM TO CRASH OF COURSE (CEC) }
  178. InitialSeed:=FALSE;
  179. OldRandSeed:=RandSeed;
  180. NewSeed;
  181. end;
  182. Inc(RandSeed);
  183. RandSeed := (RandSeed * 998) mod 1000003;
  184. OldRandSeed:=RandSeed;
  185. if l<>0 then
  186. begin
  187. internRandom := RandSeed mod l;
  188. end
  189. else internRandom:=0;
  190. end;
  191. function random(l:cardinal): cardinal;
  192. begin
  193. random := trunc(random()*l);
  194. end;
  195. {$ifndef cardinalmulfixed}
  196. function random(l:longint): longint;
  197. begin
  198. random := trunc(random()*l);
  199. end;
  200. {$endif cardinalmulfixed}
  201. Procedure NewSeed;
  202. begin
  203. randseed := randseed mod 1000003;
  204. Seed2 := (internRandom(65000) * internRandom(65000)) mod 600011;
  205. Seed3 := (internRandom(65000) * internRandom(65000)) mod 765241;
  206. end;
  207. { Include processor specific routines }
  208. {$I math.inc}
  209. {$ifdef INT64}
  210. {$I int64.inc}
  211. {$endif INT64}
  212. {****************************************************************************
  213. Memory Management
  214. ****************************************************************************}
  215. {$ifndef RTLLITE}
  216. Function Ptr(sel,off : Longint) : pointer;[internconst:in_const_ptr];
  217. Begin
  218. sel:=0;
  219. ptr:=pointer(off);
  220. End;
  221. Function CSeg : Word;
  222. Begin
  223. Cseg:=0;
  224. End;
  225. Function DSeg : Word;
  226. Begin
  227. Dseg:=0;
  228. End;
  229. Function SSeg : Word;
  230. Begin
  231. Sseg:=0;
  232. End;
  233. {$endif RTLLITE}
  234. {*****************************************************************************
  235. Directory support.
  236. *****************************************************************************}
  237. Procedure getdir(drivenr:byte;Var dir:ansistring);
  238. { this is needed to also allow ansistrings, the shortstring version is
  239. OS dependent }
  240. var
  241. s : shortstring;
  242. begin
  243. getdir(drivenr,s);
  244. dir:=s;
  245. end;
  246. {*****************************************************************************
  247. Miscellaneous
  248. *****************************************************************************}
  249. procedure int_overflow;[public,alias:'FPC_OVERFLOW'];
  250. begin
  251. HandleErrorFrame(215,get_frame);
  252. end;
  253. {$ifdef HASSAVEREGISTERS}
  254. procedure int_iocheck(addr : longint);[saveregisters,public,alias:'FPC_IOCHECK'];
  255. var
  256. l : longint;
  257. begin
  258. if InOutRes<>0 then
  259. begin
  260. l:=InOutRes;
  261. InOutRes:=0;
  262. HandleErrorFrame(l,get_frame);
  263. end;
  264. end;
  265. {$endif}
  266. Function IOResult:Word;
  267. Begin
  268. IOResult:=InOutRes;
  269. InOutRes:=0;
  270. End;
  271. procedure fillchar(var x;count : longint;value : boolean);
  272. begin
  273. fillchar(x,count,byte(value));
  274. end;
  275. procedure fillchar(var x;count : longint;value : char);
  276. begin
  277. fillchar(x,count,byte(value));
  278. end;
  279. {*****************************************************************************
  280. Initialization / Finalization
  281. *****************************************************************************}
  282. const
  283. maxunits=1024; { See also files.pas of the compiler source }
  284. type
  285. TInitFinalRec=record
  286. InitProc,
  287. FinalProc : TProcedure;
  288. end;
  289. TInitFinalTable=record
  290. TableCount,
  291. InitCount : longint;
  292. Procs : array[1..maxunits] of TInitFinalRec;
  293. end;
  294. var
  295. InitFinalTable : TInitFinalTable;external name 'INITFINAL';
  296. procedure InitializeUnits;[public,alias:'FPC_INITIALIZEUNITS'];
  297. var
  298. i : longint;
  299. begin
  300. with InitFinalTable do
  301. begin
  302. for i:=1to TableCount do
  303. begin
  304. if assigned(Procs[i].InitProc) then
  305. Procs[i].InitProc();
  306. InitCount:=i;
  307. end;
  308. end;
  309. end;
  310. procedure FinalizeUnits;[public,alias:'FPC_FINALIZEUNITS'];
  311. begin
  312. with InitFinalTable do
  313. begin
  314. while (InitCount>0) do
  315. begin
  316. if assigned(Procs[InitCount].FinalProc) then
  317. Procs[InitCount].FinalProc();
  318. dec(InitCount);
  319. end;
  320. end;
  321. end;
  322. {*****************************************************************************
  323. Error / Exit / ExitProc
  324. *****************************************************************************}
  325. Procedure HandleErrorFrame (Errno : longint;frame : longint);
  326. {
  327. Procedure to handle internal errors, i.e. not user-invoked errors
  328. Internal function should ALWAYS call HandleError instead of RunError.
  329. Can be used for exception handlers to specify the frame
  330. }
  331. var
  332. addr : longint;
  333. begin
  334. addr:=get_caller_addr(frame);
  335. If pointer(ErrorProc)<>Nil then
  336. ErrorProc(Errno,pointer(addr));
  337. errorcode:=Errno;
  338. exitcode:=Errno;
  339. erroraddr:=pointer(addr);
  340. errorbase:=get_caller_frame(frame);
  341. halt(errorcode);
  342. end;
  343. Procedure HandleError (Errno : longint);[public,alias : 'FPC_HANDLEERROR'];
  344. {
  345. Procedure to handle internal errors, i.e. not user-invoked errors
  346. Internal function should ALWAYS call HandleError instead of RunError.
  347. }
  348. begin
  349. HandleErrorFrame(Errno,get_frame);
  350. end;
  351. procedure runerror(w : word);[alias: 'FPC_RUNERROR'];
  352. begin
  353. errorcode:=w;
  354. exitcode:=w;
  355. erroraddr:=pointer(get_caller_addr(get_frame));
  356. errorbase:=get_caller_frame(get_frame);
  357. halt(errorcode);
  358. end;
  359. Procedure RunError;
  360. Begin
  361. RunError (0);
  362. End;
  363. Procedure Halt;
  364. Begin
  365. Halt(0);
  366. End;
  367. Procedure dump_stack(var f : text;bp : Longint);
  368. var
  369. i, prevbp : Longint;
  370. Begin
  371. prevbp:=bp-1;
  372. i:=0;
  373. while bp > prevbp Do
  374. Begin
  375. Writeln(f,' 0x',HexStr(get_caller_addr(bp),8));
  376. Inc(i);
  377. If i>max_frame_dump Then
  378. exit;
  379. prevbp:=bp;
  380. bp:=get_caller_frame(bp);
  381. End;
  382. End;
  383. Procedure system_exit;forward;
  384. Procedure do_exit;[Public,Alias:'FPC_DO_EXIT'];
  385. var
  386. current_exit : Procedure;
  387. Begin
  388. while exitProc<>nil Do
  389. Begin
  390. InOutRes:=0;
  391. current_exit:=tProcedure(exitProc);
  392. exitProc:=nil;
  393. current_exit();
  394. End;
  395. { Finalize units }
  396. FinalizeUnits;
  397. { Show runtime error }
  398. If erroraddr<>nil Then
  399. Begin
  400. Writeln(stdout,'Runtime error ',Errorcode,' at 0x',hexstr(Longint(Erroraddr),8));
  401. { to get a nice symify }
  402. Writeln(stdout,' 0x',HexStr(Longint(Erroraddr),8));
  403. dump_stack(stdout,ErrorBase);
  404. Writeln(stdout,'');
  405. End;
  406. { call system dependent exit code }
  407. System_exit;
  408. End;
  409. Type
  410. PExitProcInfo = ^TExitProcInfo;
  411. TExitProcInfo = Record
  412. Next : PExitProcInfo;
  413. SaveExit : Pointer;
  414. Proc : TProcedure;
  415. End;
  416. const
  417. ExitProcList: PExitProcInfo = nil;
  418. Procedure DoExitProc;
  419. var
  420. P : PExitProcInfo;
  421. Proc : TProcedure;
  422. Begin
  423. P:=ExitProcList;
  424. ExitProcList:=P^.Next;
  425. ExitProc:=P^.SaveExit;
  426. Proc:=P^.Proc;
  427. DisPose(P);
  428. Proc();
  429. End;
  430. Procedure AddExitProc(Proc: TProcedure);
  431. var
  432. P : PExitProcInfo;
  433. Begin
  434. New(P);
  435. P^.Next:=ExitProcList;
  436. P^.SaveExit:=ExitProc;
  437. P^.Proc:=Proc;
  438. ExitProcList:=P;
  439. ExitProc:=@DoExitProc;
  440. End;
  441. {*****************************************************************************
  442. Abstract/Assert support.
  443. *****************************************************************************}
  444. procedure AbstractError;[public,alias : 'FPC_ABSTRACTERROR'];
  445. begin
  446. If pointer(AbstractErrorProc)<>nil then
  447. AbstractErrorProc();
  448. HandleErrorFrame(211,get_frame);
  449. end;
  450. Procedure int_assert(Const Msg,FName:Shortstring;LineNo,ErrorAddr:Longint); [{$ifdef HASSAVEREGISTERS}SaveRegisters,{$endif}Public,Alias : 'FPC_ASSERT'];
  451. begin
  452. if pointer(AssertErrorProc)<>nil then
  453. AssertErrorProc(Msg,FName,LineNo,ErrorAddr)
  454. else
  455. HandleErrorFrame(227,get_frame);
  456. end;
  457. Procedure SysAssert(Const Msg,FName:Shortstring;LineNo,ErrorAddr:Longint);
  458. begin
  459. If msg='' then
  460. write(stderr,'Assertion failed')
  461. else
  462. write(stderr,msg);
  463. Writeln(stderr,' (',FName,', line ',LineNo,').');
  464. Writeln(stderr,'');
  465. end;
  466. {*****************************************************************************
  467. SetJmp/LongJmp support.
  468. *****************************************************************************}
  469. {$i setjump.inc}
  470. {*****************************************************************************
  471. Object Pascal support
  472. *****************************************************************************}
  473. {$i objpas.inc}
  474. {
  475. $Log$
  476. Revision 1.79 2000-01-07 16:41:36 daniel
  477. * copyright 2000
  478. Revision 1.78 2000/01/07 16:32:25 daniel
  479. * copyright 2000 added
  480. Revision 1.77 1999/12/21 11:10:22 pierre
  481. * allow v09912 to compile system
  482. Revision 1.76 1999/12/18 14:54:34 florian
  483. * very basic widestring support
  484. Revision 1.75 1999/12/12 13:29:34 jonas
  485. * remove "random(longint): longint" if cardinalmulfixed is defined
  486. Revision 1.74 1999/12/01 12:37:13 jonas
  487. + function random(longint): longint
  488. Revision 1.73 1999/11/20 12:48:09 jonas
  489. * reinstated old random generator, but modified it so the integer
  490. one now has a much longer period
  491. Revision 1.72 1999/11/15 21:49:47 peter
  492. * exception address fixes
  493. Revision 1.71 1999/11/09 22:40:12 pierre
  494. + get also first BackTrace address with ' 0x' prefix
  495. Revision 1.70 1999/11/09 20:14:12 daniel
  496. * Committed new random generator.
  497. Revision 1.69 1999/11/06 14:35:39 peter
  498. * truncated log
  499. Revision 1.68 1999/10/26 12:31:00 peter
  500. * *errorproc are not procvars instead of pointers which allows better
  501. error checking for the parameters (shortstring<->ansistring)
  502. Revision 1.67 1999/09/18 16:05:12 jonas
  503. * dump_stack now actually dumps its info to f (was still hardcoded
  504. to stderr)
  505. Revision 1.66 1999/08/05 23:45:14 peter
  506. * saveregister is now working and used for assert and iocheck (which has
  507. been moved to system.inc because it's now system independent)
  508. Revision 1.65 1999/07/28 12:58:22 peter
  509. * fixed assert() to push/pop registers
  510. Revision 1.64 1999/07/05 20:04:27 peter
  511. * removed temp defines
  512. Revision 1.63 1999/07/03 01:24:19 peter
  513. * $ifdef int64
  514. Revision 1.62 1999/07/02 18:06:42 florian
  515. + qword/int64: lo/hi/swap
  516. Revision 1.61 1999/07/01 15:39:51 florian
  517. + qword/int64 type released
  518. Revision 1.60 1999/06/11 11:47:00 peter
  519. * random doesn't rte 200 with random(0)
  520. Revision 1.59 1999/06/05 20:45:12 michael
  521. + AbstractErro should call HandleError, not runerror.
  522. Revision 1.58 1999/05/17 21:52:39 florian
  523. * most of the Object Pascal stuff moved to the system unit
  524. Revision 1.57 1999/04/17 13:10:25 peter
  525. * addr() internal
  526. Revision 1.56 1999/04/15 12:20:01 peter
  527. + finalization support
  528. Revision 1.55 1999/03/01 15:41:03 peter
  529. * use external names
  530. * removed all direct assembler modes
  531. Revision 1.54 1999/02/01 00:05:14 florian
  532. + functions lo/hi for DWord type implemented
  533. Revision 1.53 1999/01/29 09:23:09 pierre
  534. * Fillchar(..,..,boolean) added
  535. Revision 1.52 1999/01/22 12:39:23 pierre
  536. + added text arg for dump_stack
  537. Revision 1.51 1999/01/18 10:05:52 pierre
  538. + system_exit procedure added
  539. Revision 1.50 1998/12/28 15:50:46 peter
  540. + stdout, which is needed when you write something in the system unit
  541. to the screen. Like the runtime error
  542. Revision 1.49 1998/12/21 14:28:21 pierre
  543. * HandleError -> HandleErrorFrame to avoid problem in
  544. assembler code in i386.inc
  545. (call to overloaded function in assembler block !)
  546. }