system.inc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Run time library.
  4. Copyright (c) 1993,97 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 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 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 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.76 1999-12-18 14:54:34 florian
  477. * very basic widestring support
  478. Revision 1.75 1999/12/12 13:29:34 jonas
  479. * remove "random(longint): longint" if cardinalmulfixed is defined
  480. Revision 1.74 1999/12/01 12:37:13 jonas
  481. + function random(longint): longint
  482. Revision 1.73 1999/11/20 12:48:09 jonas
  483. * reinstated old random generator, but modified it so the integer
  484. one now has a much longer period
  485. Revision 1.72 1999/11/15 21:49:47 peter
  486. * exception address fixes
  487. Revision 1.71 1999/11/09 22:40:12 pierre
  488. + get also first BackTrace address with ' 0x' prefix
  489. Revision 1.70 1999/11/09 20:14:12 daniel
  490. * Committed new random generator.
  491. Revision 1.69 1999/11/06 14:35:39 peter
  492. * truncated log
  493. Revision 1.68 1999/10/26 12:31:00 peter
  494. * *errorproc are not procvars instead of pointers which allows better
  495. error checking for the parameters (shortstring<->ansistring)
  496. Revision 1.67 1999/09/18 16:05:12 jonas
  497. * dump_stack now actually dumps its info to f (was still hardcoded
  498. to stderr)
  499. Revision 1.66 1999/08/05 23:45:14 peter
  500. * saveregister is now working and used for assert and iocheck (which has
  501. been moved to system.inc because it's now system independent)
  502. Revision 1.65 1999/07/28 12:58:22 peter
  503. * fixed assert() to push/pop registers
  504. Revision 1.64 1999/07/05 20:04:27 peter
  505. * removed temp defines
  506. Revision 1.63 1999/07/03 01:24:19 peter
  507. * $ifdef int64
  508. Revision 1.62 1999/07/02 18:06:42 florian
  509. + qword/int64: lo/hi/swap
  510. Revision 1.61 1999/07/01 15:39:51 florian
  511. + qword/int64 type released
  512. Revision 1.60 1999/06/11 11:47:00 peter
  513. * random doesn't rte 200 with random(0)
  514. Revision 1.59 1999/06/05 20:45:12 michael
  515. + AbstractErro should call HandleError, not runerror.
  516. Revision 1.58 1999/05/17 21:52:39 florian
  517. * most of the Object Pascal stuff moved to the system unit
  518. Revision 1.57 1999/04/17 13:10:25 peter
  519. * addr() internal
  520. Revision 1.56 1999/04/15 12:20:01 peter
  521. + finalization support
  522. Revision 1.55 1999/03/01 15:41:03 peter
  523. * use external names
  524. * removed all direct assembler modes
  525. Revision 1.54 1999/02/01 00:05:14 florian
  526. + functions lo/hi for DWord type implemented
  527. Revision 1.53 1999/01/29 09:23:09 pierre
  528. * Fillchar(..,..,boolean) added
  529. Revision 1.52 1999/01/22 12:39:23 pierre
  530. + added text arg for dump_stack
  531. Revision 1.51 1999/01/18 10:05:52 pierre
  532. + system_exit procedure added
  533. Revision 1.50 1998/12/28 15:50:46 peter
  534. + stdout, which is needed when you write something in the system unit
  535. to the screen. Like the runtime error
  536. Revision 1.49 1998/12/21 14:28:21 pierre
  537. * HandleError -> HandleErrorFrame to avoid problem in
  538. assembler code in i386.inc
  539. (call to overloaded function in assembler block !)
  540. }