system.inc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  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. 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 chr(b : byte) : Char; [INTERNPROC: In_chr_byte];
  50. Function Length(s : string) : byte; [INTERNPROC: In_Length_string];
  51. Function Length(c : char) : byte; [INTERNPROC: In_Length_string];
  52. Procedure Reset(var f : TypedFile); [INTERNPROC: In_Reset_TypedFile];
  53. Procedure Rewrite(var f : TypedFile); [INTERNPROC: In_Rewrite_TypedFile];
  54. {****************************************************************************
  55. Include processor specific routines
  56. ****************************************************************************}
  57. {$IFDEF I386}
  58. {$IFDEF M68K}
  59. {$Error Can't determine processor type !}
  60. {$ENDIF}
  61. {$I i386.inc} { Case dependent, don't change }
  62. {$ELSE}
  63. {$IFDEF M68K}
  64. {$I m68k.inc} { Case dependent, don't change }
  65. {$ELSE}
  66. {$Error Can't determine processor type !}
  67. {$ENDIF}
  68. {$ENDIF}
  69. {****************************************************************************
  70. Set Handling
  71. ****************************************************************************}
  72. { Include set support which is processor specific}
  73. {$I set.inc}
  74. {****************************************************************************
  75. Subroutines for String handling
  76. ****************************************************************************}
  77. { Needs to be before RTTI handling }
  78. {$i sstrings.inc}
  79. Type
  80. PLongint = ^Longint;
  81. PByte = ^Byte;
  82. {$i astrings.inc}
  83. {****************************************************************************
  84. Run-Time Type Information (RTTI)
  85. ****************************************************************************}
  86. {$i rtti.inc}
  87. {****************************************************************************
  88. Math Routines
  89. ****************************************************************************}
  90. {$ifndef RTLLITE}
  91. function Hi(b : byte): byte;
  92. begin
  93. Hi := b shr 4
  94. end;
  95. function Lo(b : byte): byte;
  96. begin
  97. Lo := b and $0f
  98. end;
  99. Function swap (X : Word) : Word;[internconst:in_const_swap_word];
  100. Begin
  101. swap:=(X and $ff) shl 8 + (X shr 8)
  102. End;
  103. Function Swap (X : Integer) : Integer;[internconst:in_const_swap_word];
  104. Begin
  105. Swap:=Integer(Swap(Word(X)));
  106. End;
  107. Function swap (X : Longint) : Longint;[internconst:in_const_swap_long];
  108. Begin
  109. Swap:=(X and $ffff) shl 16 + (X shr 16)
  110. End;
  111. Function Swap (X : Cardinal) : Cardinal;[internconst:in_const_swap_long];
  112. Begin
  113. Swap:=Swap(Longint(X));
  114. End;
  115. {$endif RTLLITE}
  116. {****************************************************************************
  117. Random function routines
  118. This implements a very long cycle random number generator by combining
  119. three independant generators. The technique was described in the March
  120. 1987 issue of Byte.
  121. Taken and modified with permission from the PCQ Pascal rtl code.
  122. ****************************************************************************}
  123. {$R-}
  124. {$Q-}
  125. Procedure UseSeed(seed : Longint);Forward;
  126. Function Random : Real;
  127. var
  128. ReturnValue : Real;
  129. begin
  130. if (InitialSeed) OR ((RandSeed <> OldRandSeed) AND (NOT InitialSeed)) then
  131. Begin
  132. { This is a pretty complicated affair }
  133. { Initially we must call UseSeed when RandSeed is initalized }
  134. { We must also call UseSeed each time RandSeed is reinitialized }
  135. { DO NOT CHANGE THE ORDER OF DECLARATIONS IN THIS BLOCK }
  136. { UNLESS YOU WANT RANDON TO CRASH OF COURSE (CEC) }
  137. InitialSeed:=FALSE;
  138. OldRandSeed:=RandSeed;
  139. UseSeed(RandSeed);
  140. end;
  141. Inc(RandSeed);
  142. RandSeed := (RandSeed * 706) mod 500009;
  143. OldRandSeed:=RandSeed;
  144. INC(Seed2);
  145. Seed2 := (Seed2 * 774) MOD 600011;
  146. INC(Seed3);
  147. Seed3 := (Seed3 * 871) MOD 765241;
  148. ReturnValue := RandSeed/500009.0 +
  149. Seed2/600011.0 +
  150. Seed3/765241.0;
  151. Random := frac(ReturnValue);
  152. end;
  153. Function Random(l : Longint) : Longint;
  154. begin
  155. if (InitialSeed) OR ((RandSeed <> OldRandSeed) AND (NOT InitialSeed)) then
  156. Begin
  157. { This is a pretty complicated affair }
  158. { Initially we must call UseSeed when RandSeed is initalized }
  159. { We must also call UseSeed each time RandSeed is reinitialized }
  160. { DO NOT CHANGE THE ORDER OF DECLARATIONS IN THIS BLOCK }
  161. { UNLESS YOU WANT RANDON TO CRASH OF COURSE (CEC) }
  162. InitialSeed:=FALSE;
  163. OldRandSeed:=RandSeed;
  164. UseSeed(Randseed);
  165. end;
  166. Inc(RandSeed);
  167. RandSeed := (RandSeed * 998) mod 1000003;
  168. OldRandSeed:=RandSeed;
  169. Random := RandSeed mod l;
  170. end;
  171. Procedure UseSeed(seed : Longint);
  172. begin
  173. randseed := seed mod 1000003;
  174. Seed2 := (Random(65000) * Random(65000)) mod 600011;
  175. Seed3 := (Random(65000) * Random(65000)) mod 765241;
  176. end;
  177. { Include processor specific routines }
  178. {$I math.inc}
  179. {****************************************************************************
  180. Memory Management
  181. ****************************************************************************}
  182. {$ifndef RTLLITE}
  183. Function Ptr(sel,off : Longint) : pointer;[internconst:in_const_ptr];
  184. Begin
  185. sel:=0;
  186. ptr:=pointer(off);
  187. End;
  188. Function Addr (Var X) : Pointer;
  189. Begin
  190. Addr:=@(X);
  191. End;
  192. Function CSeg : Word;
  193. Begin
  194. Cseg:=0;
  195. End;
  196. Function DSeg : Word;
  197. Begin
  198. Dseg:=0;
  199. End;
  200. Function SSeg : Word;
  201. Begin
  202. Sseg:=0;
  203. End;
  204. {$endif RTLLITE}
  205. {*****************************************************************************
  206. Directory support.
  207. *****************************************************************************}
  208. Procedure getdir(drivenr:byte;Var dir:ansistring);
  209. { this is needed to also allow ansistrings, the shortstring version is
  210. OS dependent }
  211. var
  212. s : shortstring;
  213. begin
  214. getdir(drivenr,s);
  215. dir:=s;
  216. end;
  217. {*****************************************************************************
  218. Miscellaneous
  219. *****************************************************************************}
  220. procedure int_overflow;[public,alias:'FPC_OVERFLOW'];
  221. begin
  222. HandleErrorFrame(215,get_frame);
  223. end;
  224. Function IOResult:Word;
  225. Begin
  226. IOResult:=InOutRes;
  227. InOutRes:=0;
  228. End;
  229. procedure fillchar(var x;count : longint;value : boolean);
  230. begin
  231. fillchar(x,count,byte(value));
  232. end;
  233. procedure fillchar(var x;count : longint;value : char);
  234. begin
  235. fillchar(x,count,byte(value));
  236. end;
  237. {*****************************************************************************
  238. Init / Exit / ExitProc
  239. *****************************************************************************}
  240. {$ifdef HASFINALIZE}
  241. const
  242. maxunits=1024; { See also files.pas of the compiler source }
  243. type
  244. TInitFinalRec=record
  245. InitProc,
  246. FinalProc : TProcedure;
  247. end;
  248. TInitFinalTable=record
  249. TableCount,
  250. InitCount : longint;
  251. Procs : array[1..maxunits] of TInitFinalRec;
  252. end;
  253. var
  254. InitFinalTable : TInitFinalTable;external name 'INITFINAL';
  255. procedure InitializeUnits;[public,alias:'FPC_INITIALIZEUNITS'];
  256. var
  257. i : longint;
  258. begin
  259. with InitFinalTable do
  260. begin
  261. for i:=1to TableCount do
  262. begin
  263. if assigned(Procs[i].InitProc) then
  264. Procs[i].InitProc();
  265. InitCount:=i;
  266. end;
  267. end;
  268. end;
  269. procedure FinalizeUnits;[public,alias:'FPC_FINALIZEUNITS'];
  270. begin
  271. with InitFinalTable do
  272. begin
  273. while (InitCount>0) do
  274. begin
  275. if assigned(Procs[InitCount].FinalProc) then
  276. Procs[InitCount].FinalProc();
  277. dec(InitCount);
  278. end;
  279. end;
  280. end;
  281. {$endif}
  282. Procedure HandleErrorFrame (Errno : longint;frame : longint);
  283. {
  284. Procedure to handle internal errors, i.e. not user-invoked errors
  285. Internal function should ALWAYS call HandleError instead of RunError.
  286. Can be used for exception handlers to specify the frame
  287. }
  288. var
  289. addr : longint;
  290. begin
  291. addr:=get_caller_addr(frame);
  292. If ErrorProc<>Nil then
  293. TErrorProc (ErrorProc)(Errno,pointer(addr));
  294. errorcode:=Errno;
  295. exitcode:=Errno;
  296. erroraddr:=pointer(addr);
  297. errorbase:=get_caller_frame(frame);
  298. halt(errorcode);
  299. end;
  300. Procedure HandleError (Errno : longint);[public,alias : 'FPC_HANDLEERROR'];
  301. {
  302. Procedure to handle internal errors, i.e. not user-invoked errors
  303. Internal function should ALWAYS call HandleError instead of RunError.
  304. }
  305. begin
  306. HandleErrorFrame(Errno,get_frame);
  307. end;
  308. procedure runerror(w : word);[alias: 'FPC_RUNERROR'];
  309. begin
  310. errorcode:=w;
  311. exitcode:=w;
  312. erroraddr:=pointer(get_caller_addr(get_frame));
  313. errorbase:=get_caller_frame(get_frame);
  314. halt(errorcode);
  315. end;
  316. Procedure RunError;
  317. Begin
  318. RunError (0);
  319. End;
  320. Procedure Halt;
  321. Begin
  322. Halt(0);
  323. End;
  324. Procedure dump_stack(var f : text;bp : Longint);
  325. var
  326. i, prevbp : Longint;
  327. Begin
  328. prevbp:=bp-1;
  329. i:=0;
  330. while bp > prevbp Do
  331. Begin
  332. Writeln(stderr,' 0x',HexStr(get_caller_addr(bp),8));
  333. Inc(i);
  334. If i>max_frame_dump Then
  335. exit;
  336. prevbp:=bp;
  337. bp:=get_caller_frame(bp);
  338. End;
  339. End;
  340. Procedure system_exit;forward;
  341. Procedure do_exit;[Public,Alias:'FPC_DO_EXIT'];
  342. var
  343. current_exit : Procedure;
  344. Begin
  345. while exitProc<>nil Do
  346. Begin
  347. InOutRes:=0;
  348. current_exit:=tProcedure(exitProc);
  349. exitProc:=nil;
  350. current_exit();
  351. End;
  352. {$ifdef HASFINALIZE}
  353. { Finalize units }
  354. FinalizeUnits;
  355. {$endif}
  356. { Show runtime error }
  357. If erroraddr<>nil Then
  358. Begin
  359. Writeln(stdout,'Run time error ',Errorcode,' at 0x',hexstr(Longint(Erroraddr),8));
  360. dump_stack(stdout,ErrorBase);
  361. End;
  362. { call system dependent exit code }
  363. System_exit;
  364. End;
  365. Type
  366. PExitProcInfo = ^TExitProcInfo;
  367. TExitProcInfo = Record
  368. Next : PExitProcInfo;
  369. SaveExit : Pointer;
  370. Proc : TProcedure;
  371. End;
  372. const
  373. ExitProcList: PExitProcInfo = nil;
  374. Procedure DoExitProc;
  375. var
  376. P : PExitProcInfo;
  377. Proc : TProcedure;
  378. Begin
  379. P:=ExitProcList;
  380. ExitProcList:=P^.Next;
  381. ExitProc:=P^.SaveExit;
  382. Proc:=P^.Proc;
  383. DisPose(P);
  384. Proc();
  385. End;
  386. Procedure AddExitProc(Proc: TProcedure);
  387. var
  388. P : PExitProcInfo;
  389. Begin
  390. New(P);
  391. P^.Next:=ExitProcList;
  392. P^.SaveExit:=ExitProc;
  393. P^.Proc:=Proc;
  394. ExitProcList:=P;
  395. ExitProc:=@DoExitProc;
  396. End;
  397. {*****************************************************************************
  398. Abstract/Assert support.
  399. *****************************************************************************}
  400. procedure AbstractError;[public,alias : 'FPC_ABSTRACTERROR'];
  401. Type
  402. TAbstractErrorProc=Procedure;
  403. begin
  404. If AbstractErrorProc<>nil then
  405. TAbstractErrorProc(AbstractErrorProc);
  406. RunError(211);
  407. end;
  408. Procedure int_assert(Const Msg,FName:string;LineNo,ErrorAddr:Longint); [Public,Alias : 'FPC_ASSERT'];
  409. type
  410. TAssertErrorProc=procedure(const msg,fname:string;lineno,erroraddr:longint);
  411. begin
  412. if AssertErrorProc<>nil then
  413. TAssertErrorProc(AssertErrorProc)(Msg,FName,LineNo,ErrorAddr)
  414. else
  415. HandleError(227);
  416. end;
  417. Procedure SysAssert(Const Msg,FName:string;LineNo,ErrorAddr:Longint);
  418. begin
  419. If msg='' then
  420. write(stderr,'Assertion failed')
  421. else
  422. write(stderr,msg);
  423. writeln(stderr,' (',FName,', line ',LineNo,').');
  424. end;
  425. {*****************************************************************************
  426. SetJmp/LongJmp support.
  427. *****************************************************************************}
  428. {$i setjump.inc}
  429. {
  430. $Log$
  431. Revision 1.56 1999-04-15 12:20:01 peter
  432. + finalization support
  433. Revision 1.55 1999/03/01 15:41:03 peter
  434. * use external names
  435. * removed all direct assembler modes
  436. Revision 1.54 1999/02/01 00:05:14 florian
  437. + functions lo/hi for DWord type implemented
  438. Revision 1.53 1999/01/29 09:23:09 pierre
  439. * Fillchar(..,..,boolean) added
  440. Revision 1.52 1999/01/22 12:39:23 pierre
  441. + added text arg for dump_stack
  442. Revision 1.51 1999/01/18 10:05:52 pierre
  443. + system_exit procedure added
  444. Revision 1.50 1998/12/28 15:50:46 peter
  445. + stdout, which is needed when you write something in the system unit
  446. to the screen. Like the runtime error
  447. Revision 1.49 1998/12/21 14:28:21 pierre
  448. * HandleError -> HandleErrorFrame to avoid problem in
  449. assembler code in i386.inc
  450. (call to overloaded function in assembler block !)
  451. Revision 1.48 1998/12/18 17:21:33 peter
  452. * fixed io-error handling
  453. Revision 1.47 1998/12/15 22:43:03 peter
  454. * removed temp symbols
  455. Revision 1.46 1998/12/10 23:59:56 peter
  456. * removed warnign
  457. Revision 1.45 1998/12/01 14:00:10 pierre
  458. + added conversion from exceptions into run time error
  459. (only if syswin32 compiled with -ddebug for now !)
  460. * added HandleError(errno,frame)
  461. where you specify the frame
  462. needed for win32 exception handling
  463. Revision 1.44 1998/11/26 23:16:15 jonas
  464. * changed RandSeed and OldRandSeed to Cardinal to avoid negative random numbers
  465. Revision 1.43 1998/11/17 10:36:07 michael
  466. + renamed astrings.pp to astrings.inc
  467. Revision 1.42 1998/11/16 10:21:25 peter
  468. * fixes for H+
  469. Revision 1.41 1998/11/05 10:29:36 pierre
  470. * fix for length(char) in const expressions
  471. Revision 1.40 1998/11/04 20:34:02 michael
  472. + Removed ifdef useansistrings
  473. Revision 1.39 1998/10/12 22:11:28 jonas
  474. * fixed RandSeed bug
  475. Revision 1.38 1998/10/12 12:43:37 florian
  476. * made FPC_HANDLEERROR public
  477. Revision 1.37 1998/10/07 11:40:08 jonas
  478. * changed seed2 and seed3 to cardinal to prevent overflow
  479. Revision 1.36 1998/10/05 12:32:51 peter
  480. + assert() support
  481. Revision 1.35 1998/10/02 09:25:11 peter
  482. * more constant expression evals
  483. Revision 1.34 1998/09/22 15:30:54 peter
  484. * shortstring=string type added
  485. Revision 1.33 1998/09/16 13:08:03 michael
  486. Added AbstractErrorHandler
  487. Revision 1.32 1998/09/16 12:37:07 michael
  488. Added FPC_ prefix to abstracterror
  489. Revision 1.31 1998/09/15 17:12:32 michael
  490. + Merged changes from fixes branch
  491. Revision 1.30 1998/09/14 10:48:20 peter
  492. * FPC_ names
  493. * Heap manager is now system independent
  494. Revision 1.29.2.1 1998/09/15 17:08:43 michael
  495. + Added abstracterror call
  496. Revision 1.29 1998/09/01 17:36:21 peter
  497. + internconst
  498. Revision 1.28 1998/08/17 12:24:16 carl
  499. + important comment added
  500. Revision 1.27 1998/08/13 16:22:11 jonas
  501. * random now returns a value between 0 and max-1 instead of between 0 and max
  502. Revision 1.26 1998/08/11 00:05:26 peter
  503. * $ifdef ver0_99_5 updates
  504. Revision 1.25 1998/07/30 13:26:18 michael
  505. + Added support for ErrorProc variable. All internal functions are required
  506. to call HandleError instead of runerror from now on.
  507. This is necessary for exception support.
  508. Revision 1.24 1998/07/28 20:37:45 michael
  509. + added setjmp/longjmp and exception support
  510. Revision 1.23 1998/07/23 19:53:20 michael
  511. + Adapted assert to Delphi format
  512. Revision 1.22 1998/07/23 13:08:41 michael
  513. + Implemented DO_ASSERT function.
  514. Revision 1.21 1998/07/15 12:09:35 carl
  515. * would not compile under FPC v0.99.5
  516. Revision 1.20 1998/07/13 21:19:12 florian
  517. * some problems with ansi string support fixed
  518. Revision 1.19 1998/07/08 11:56:55 carl
  519. * randon and Random(l) now work correctly - don't touch it works!
  520. Revision 1.18 1998/07/02 13:01:55 carl
  521. * hmmm... it is luck (BSS zeroed with GAS) that DoError and ErrorBase work.
  522. Now they are initilized instead.
  523. Revision 1.17 1998/07/02 12:53:09 carl
  524. * DOERROR RESOTRED! DON'T TOUCH :)
  525. Revision 1.16 1998/07/02 12:11:50 carl
  526. * no SINGLE in m68k and other processors!
  527. Revision 1.15 1998/07/02 09:25:05 peter
  528. * fixed do_error in runtimeerror
  529. Revision 1.14 1998/07/01 15:29:59 peter
  530. * better readln/writeln
  531. Revision 1.13 1998/06/26 08:21:09 daniel
  532. - Doerror removed.
  533. Revision 1.12 1998/06/25 14:04:25 peter
  534. + internal inc/dec
  535. Revision 1.11 1998/06/25 09:44:20 daniel
  536. + RTLLITE directive to compile minimal RTL.
  537. Revision 1.10 1998/06/15 15:16:26 daniel
  538. * RTLLITE conditional added to produce smaller RTL
  539. Revision 1.9 1998/06/10 07:46:45 michael
  540. + Forgot to commit some changes
  541. Revision 1.8 1998/06/08 12:38:24 michael
  542. Implemented rtti, inserted ansistrings again
  543. Revision 1.7 1998/06/04 23:46:01 peter
  544. * comp,extended are only i386 added support_comp,support_extended
  545. Revision 1.6 1998/05/20 11:23:09 cvs
  546. * test commit. Shouldn't be allowed.
  547. Revision 1.5 1998/05/12 10:42:45 peter
  548. * moved getopts to inc/, all supported OS's need argc,argv exported
  549. + strpas, strlen are now exported in the systemunit
  550. * removed logs
  551. * removed $ifdef ver_above
  552. Revision 1.4 1998/04/16 12:30:47 peter
  553. + inc(pchar), dec(pchar), incc(pchar,a),dec(pchar,a)
  554. Revision 1.3 1998/04/08 07:53:32 michael
  555. + Changed Random() function. Moved from system to processor dependent files (from Pedro Gimeno)
  556. }