system.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  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. { no stack check in system }
  12. {$S-}
  13. unit system;
  14. interface
  15. {$define StdErrToConsole}
  16. {$ifdef SYSTEMDEBUG}
  17. {$define SYSTEMEXCEPTIONDEBUG}
  18. {$endif SYSTEMDEBUG}
  19. {$ifdef cpui386}
  20. {$define Set_i386_Exception_handler}
  21. {$endif cpui386}
  22. { include system-independent routine headers }
  23. {$I systemh.inc}
  24. {Platform specific information}
  25. const
  26. LineEnding = #13#10;
  27. LFNSupport = false; { ??? - that's how it was declared in dos.pp! }
  28. DirectorySeparator = '\';
  29. DriveSeparator = ':';
  30. PathSeparator = ';';
  31. { FileNameCaseSensitive is defined separately below!!! }
  32. type
  33. { the fields of this record are os dependent }
  34. { and they shouldn't be used in a program }
  35. { only the type TCriticalSection is important }
  36. TRTLCriticalSection = packed record
  37. SemaHandle : LONGINT;
  38. SemaIsOpen : BOOLEAN;
  39. end;
  40. { include threading stuff }
  41. { i threadh.inc}
  42. { include heap support headers }
  43. {$I heaph.inc}
  44. CONST
  45. { Default filehandles }
  46. UnusedHandle : longint = -1;
  47. StdInputHandle : longint = 0;
  48. StdOutputHandle : longint = 0;
  49. StdErrorHandle : longint = 0;
  50. FileNameCaseSensitive : boolean = false;
  51. sLineBreak = LineEnding;
  52. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  53. TYPE
  54. TNWCheckFunction = procedure (var code : longint);
  55. VAR
  56. ArgC : INTEGER;
  57. ArgV : ppchar;
  58. NetwareCheckFunction : TNWCheckFunction;
  59. NetwareMainThreadGroupID: longint;
  60. NetwareCodeStartAddress : dword;
  61. CONST
  62. envp : ppchar = nil; {dummy to make heaptrc happy}
  63. PROCEDURE ConsolePrintf (FormatStr : PCHAR; Param : LONGINT); CDecl;
  64. PROCEDURE ConsolePrintf3 (FormatStr : PCHAR; P1,P2,P3 : LONGINT); CDecl;
  65. PROCEDURE ConsolePrintf (FormatStr : PCHAR); CDecl;
  66. type
  67. TSysCloseAllRemainingSemaphores = procedure;
  68. TSysReleaseThreadVars = procedure;
  69. TSysSetThreadDataAreaPtr = function (newPtr:pointer):pointer;
  70. procedure NWSysSetThreadFunctions (crs:TSysCloseAllRemainingSemaphores;
  71. rtv:TSysReleaseThreadVars;
  72. stdata:TSysSetThreadDataAreaPtr);
  73. implementation
  74. { Indicate that stack checking is taken care by OS}
  75. {$DEFINE NO_GENERIC_STACK_CHECK}
  76. { include system independent routines }
  77. {$I system.inc}
  78. { some declarations for Netware API calls }
  79. {$I nwsys.inc}
  80. {$I errno.inc}
  81. {procedure setup_arguments;
  82. begin
  83. end;
  84. }
  85. {procedure setup_environment;
  86. begin
  87. end;
  88. }
  89. var
  90. CloseAllRemainingSemaphores : TSysCloseAllRemainingSemaphores = nil;
  91. ReleaseThreadVars : TSysReleaseThreadVars = nil;
  92. SetThreadDataAreaPtr : TSysSetThreadDataAreaPtr = nil;
  93. procedure NWSysSetThreadFunctions (crs:TSysCloseAllRemainingSemaphores;
  94. rtv:TSysReleaseThreadVars;
  95. stdata:TSysSetThreadDataAreaPtr);
  96. begin
  97. CloseAllRemainingSemaphores := crs;
  98. ReleaseThreadVars := rtv;
  99. SetThreadDataAreaPtr := stdata;
  100. end;
  101. procedure PASCALMAIN;external name 'PASCALMAIN';
  102. procedure fpc_do_exit;external name 'FPC_DO_EXIT';
  103. {*****************************************************************************
  104. Startup
  105. *****************************************************************************}
  106. function __GetBssStart : pointer; external name '__getBssStart';
  107. function __getUninitializedDataSize : longint; external name '__getUninitializedDataSize';
  108. //function __getDataStart : longint; external name '__getDataStart';
  109. function __GetTextStart : longint; external name '__getTextStart';
  110. PROCEDURE nlm_main (_ArgC : LONGINT; _ArgV : ppchar); CDECL; [public,alias: '_nlm_main'];
  111. BEGIN
  112. // Initialize BSS
  113. if __getUninitializedDataSize > 0 then
  114. fillchar (__getBssStart^,__getUninitializedDataSize,0);
  115. NetwareCodeStartAddress := __GetTextStart;
  116. ArgC := _ArgC;
  117. ArgV := _ArgV;
  118. fpc_threadvar_relocate_proc := nil;
  119. PASCALMAIN;
  120. END;
  121. {*****************************************************************************
  122. System Dependent Exit code
  123. *****************************************************************************}
  124. procedure FreeSbrkMem; forward;
  125. var SigTermHandlerActive : boolean;
  126. Procedure system_exit;
  127. begin
  128. if assigned (CloseAllRemainingSemaphores) then CloseAllRemainingSemaphores;
  129. if assigned (ReleaseThreadVars) then ReleaseThreadVars;
  130. FreeSbrkMem; { free memory allocated by heapmanager }
  131. if not SigTermHandlerActive then
  132. begin
  133. if ExitCode <> 0 Then { otherwise we dont see runtime-errors }
  134. _SetAutoScreenDestructionMode (false);
  135. _exit (ExitCode);
  136. end;
  137. end;
  138. {*****************************************************************************
  139. Stack check code
  140. *****************************************************************************}
  141. procedure int_stackcheck(stack_size:longint);[public,alias:'FPC_STACKCHECK'];
  142. {
  143. called when trying to get local stack if the compiler directive $S
  144. is set this function must preserve esi !!!! because esi is set by
  145. the calling proc for methods it must preserve all registers !!
  146. With a 2048 byte safe area used to write to StdIo without crossing
  147. the stack boundary
  148. }
  149. begin
  150. IF _stackavail > stack_size + 2048 THEN EXIT;
  151. HandleError (202);
  152. end;
  153. {*****************************************************************************
  154. ParamStr/Randomize
  155. *****************************************************************************}
  156. { number of args }
  157. function paramcount : longint;
  158. begin
  159. paramcount := argc - 1;
  160. end;
  161. { argument number l }
  162. function paramstr(l : longint) : string;
  163. begin
  164. if (l>=0) and (l+1<=argc) then
  165. paramstr:=strpas(argv[l])
  166. else
  167. paramstr:='';
  168. end;
  169. { set randseed to a new pseudo random value }
  170. procedure randomize;
  171. begin
  172. randseed := _time (NIL);
  173. end;
  174. {*****************************************************************************
  175. Heap Management
  176. *****************************************************************************}
  177. var
  178. heap : longint;external name 'HEAP';
  179. intern_heapsize : longint;external name 'HEAPSIZE';
  180. { first address of heap }
  181. function getheapstart:pointer;
  182. assembler;
  183. asm
  184. leal HEAP,%eax
  185. end ['EAX'];
  186. { current length of heap }
  187. function getheapsize:longint;
  188. assembler;
  189. asm
  190. movl intern_HEAPSIZE,%eax
  191. end ['EAX'];
  192. const HeapInitialMaxBlocks = 32;
  193. type THeapSbrkBlockList = array [1.. HeapInitialMaxBlocks] of pointer;
  194. var HeapSbrkBlockList : ^THeapSbrkBlockList = nil;
  195. HeapSbrkLastUsed : dword = 0;
  196. HeapSbrkAllocated : dword = 0;
  197. { function to allocate size bytes more for the program }
  198. { must return the first address of new data space or nil if fail }
  199. { for netware all allocated blocks are saved to free them at }
  200. { exit (to avoid message "Module did not release xx resources") }
  201. Function Sbrk(size : longint):pointer;
  202. var P2 : POINTER;
  203. begin
  204. Sbrk := _malloc (size);
  205. if Sbrk <> nil then begin
  206. if HeapSbrkBlockList = nil then
  207. begin
  208. Pointer (HeapSbrkBlockList) := _malloc (sizeof (HeapSbrkBlockList^));
  209. if HeapSbrkBlockList = nil then
  210. begin
  211. _free (Sbrk);
  212. Sbrk := nil;
  213. exit;
  214. end;
  215. fillchar (HeapSbrkBlockList^,sizeof(HeapSbrkBlockList^),0);
  216. HeapSbrkAllocated := HeapInitialMaxBlocks;
  217. end;
  218. if (HeapSbrkLastUsed = HeapSbrkAllocated) then
  219. begin { grow }
  220. p2 := _realloc (HeapSbrkBlockList, HeapSbrkAllocated + HeapInitialMaxBlocks);
  221. if p2 = nil then
  222. begin
  223. _free (Sbrk);
  224. Sbrk := nil;
  225. exit;
  226. end;
  227. inc (HeapSbrkAllocated, HeapInitialMaxBlocks);
  228. end;
  229. inc (HeapSbrkLastUsed);
  230. HeapSbrkBlockList^[HeapSbrkLastUsed] := Sbrk;
  231. end;
  232. end;
  233. procedure FreeSbrkMem;
  234. var i : longint;
  235. begin
  236. if HeapSbrkBlockList <> nil then
  237. begin
  238. for i := 1 to HeapSbrkLastUsed do
  239. _free (HeapSbrkBlockList^[i]);
  240. _free (HeapSbrkBlockList);
  241. HeapSbrkAllocated := 0;
  242. HeapSbrkLastUsed := 0;
  243. HeapSbrkBlockList := nil;
  244. end;
  245. end;
  246. { include standard heap management }
  247. {$I heap.inc}
  248. {****************************************************************************
  249. Low level File Routines
  250. All these functions can set InOutRes on errors
  251. ****************************************************************************}
  252. PROCEDURE NW2PASErr (Err : LONGINT);
  253. BEGIN
  254. if Err = 0 then { Else it will go through all the cases }
  255. exit;
  256. case Err of
  257. Sys_ENFILE,
  258. Sys_EMFILE : Inoutres:=4;
  259. Sys_ENOENT : Inoutres:=2;
  260. Sys_EBADF : Inoutres:=6;
  261. Sys_ENOMEM,
  262. Sys_EFAULT : Inoutres:=217;
  263. Sys_EINVAL : Inoutres:=218;
  264. Sys_EPIPE,
  265. Sys_EINTR,
  266. Sys_EIO,
  267. Sys_EAGAIN,
  268. Sys_ENOSPC : Inoutres:=101;
  269. Sys_ENAMETOOLONG,
  270. Sys_ELOOP,
  271. Sys_ENOTDIR : Inoutres:=3;
  272. Sys_EROFS,
  273. Sys_EEXIST,
  274. Sys_EACCES : Inoutres:=5;
  275. Sys_EBUSY : Inoutres:=162;
  276. end;
  277. END;
  278. FUNCTION errno : LONGINT;
  279. BEGIN
  280. errno := __get_errno_ptr^;
  281. END;
  282. PROCEDURE Errno2Inoutres;
  283. BEGIN
  284. NW2PASErr (errno);
  285. END;
  286. PROCEDURE SetFileError (VAR Err : LONGINT);
  287. BEGIN
  288. IF Err >= 0 THEN
  289. InOutRes := 0
  290. ELSE
  291. BEGIN
  292. Err := errno;
  293. NW2PASErr (Err);
  294. Err := 0;
  295. END;
  296. END;
  297. { close a file from the handle value }
  298. procedure do_close(handle : longint);
  299. VAR res : LONGINT;
  300. begin
  301. res := _close (handle);
  302. IF res <> 0 THEN
  303. SetFileError (res)
  304. ELSE
  305. InOutRes := 0;
  306. end;
  307. procedure do_erase(p : pchar);
  308. VAR res : LONGINT;
  309. begin
  310. res := _unlink (p);
  311. IF Res < 0 THEN
  312. SetFileError (res)
  313. ELSE
  314. InOutRes := 0;
  315. end;
  316. procedure do_rename(p1,p2 : pchar);
  317. VAR res : LONGINT;
  318. begin
  319. res := _rename (p1,p2);
  320. IF Res < 0 THEN
  321. SetFileError (res)
  322. ELSE
  323. InOutRes := 0
  324. end;
  325. function do_write(h,addr,len : longint) : longint;
  326. VAR res : LONGINT;
  327. begin
  328. res := _write (h,POINTER(addr),len);
  329. IF res > 0 THEN
  330. InOutRes := 0
  331. ELSE
  332. SetFileError (res);
  333. do_write := res;
  334. end;
  335. function do_read(h,addr,len : longint) : longint;
  336. VAR res : LONGINT;
  337. begin
  338. res := _read (h,POINTER(addr),len);
  339. IF res > 0 THEN
  340. InOutRes := 0
  341. ELSE
  342. SetFileError (res);
  343. do_read := res;
  344. end;
  345. function do_filepos(handle : longint) : longint;
  346. VAR res : LONGINT;
  347. begin
  348. InOutRes:=1;
  349. res := _tell (handle);
  350. IF res < 0 THEN
  351. SetFileError (res)
  352. ELSE
  353. InOutRes := 0;
  354. do_filepos := res;
  355. end;
  356. CONST SEEK_SET = 0; // Seek from beginning of file.
  357. SEEK_CUR = 1; // Seek from current position.
  358. SEEK_END = 2; // Seek from end of file.
  359. procedure do_seek(handle,pos : longint);
  360. VAR res : LONGINT;
  361. begin
  362. res := _lseek (handle,pos, SEEK_SET);
  363. IF res >= 0 THEN
  364. InOutRes := 0
  365. ELSE
  366. SetFileError (res);
  367. end;
  368. function do_seekend(handle:longint):longint;
  369. VAR res : LONGINT;
  370. begin
  371. res := _lseek (handle,0, SEEK_END);
  372. IF res >= 0 THEN
  373. InOutRes := 0
  374. ELSE
  375. SetFileError (res);
  376. do_seekend := res;
  377. end;
  378. function do_filesize(handle : longint) : longint;
  379. VAR res : LONGINT;
  380. begin
  381. res := _filelength (handle);
  382. IF res < 0 THEN
  383. BEGIN
  384. SetFileError (Res);
  385. do_filesize := -1;
  386. END ELSE
  387. BEGIN
  388. InOutRes := 0;
  389. do_filesize := res;
  390. END;
  391. end;
  392. { truncate at a given position }
  393. procedure do_truncate (handle,pos:longint);
  394. VAR res : LONGINT;
  395. begin
  396. res := _chsize (handle,pos);
  397. IF res <> 0 THEN
  398. SetFileError (res)
  399. ELSE
  400. InOutRes := 0;
  401. end;
  402. // mostly stolen from syslinux
  403. procedure do_open(var f;p:pchar;flags:longint);
  404. {
  405. filerec and textrec have both handle and mode as the first items so
  406. they could use the same routine for opening/creating.
  407. when (flags and $10) the file will be append
  408. when (flags and $100) the file will be truncate/rewritten
  409. when (flags and $1000) there is no check for close (needed for textfiles)
  410. }
  411. var
  412. oflags : longint;
  413. Begin
  414. { close first if opened }
  415. if ((flags and $10000)=0) then
  416. begin
  417. case FileRec(f).mode of
  418. fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
  419. fmclosed : ;
  420. else
  421. begin
  422. inoutres:=102; {not assigned}
  423. exit;
  424. end;
  425. end;
  426. end;
  427. { reset file Handle }
  428. FileRec(f).Handle:=UnusedHandle;
  429. { We do the conversion of filemodes here, concentrated on 1 place }
  430. case (flags and 3) of
  431. 0 : begin
  432. oflags := O_RDONLY;
  433. filerec(f).mode := fminput;
  434. end;
  435. 1 : begin
  436. oflags := O_WRONLY;
  437. filerec(f).mode := fmoutput;
  438. end;
  439. 2 : begin
  440. oflags := O_RDWR;
  441. filerec(f).mode := fminout;
  442. end;
  443. end;
  444. if (flags and $1000)=$1000 then
  445. oflags:=oflags or (O_CREAT or O_TRUNC)
  446. else
  447. if (flags and $100)=$100 then
  448. oflags:=oflags or (O_APPEND);
  449. { empty name is special }
  450. if p[0]=#0 then
  451. begin
  452. case FileRec(f).mode of
  453. fminput :
  454. FileRec(f).Handle:=StdInputHandle;
  455. fminout, { this is set by rewrite }
  456. fmoutput :
  457. FileRec(f).Handle:=StdOutputHandle;
  458. fmappend :
  459. begin
  460. FileRec(f).Handle:=StdOutputHandle;
  461. FileRec(f).mode:=fmoutput; {fool fmappend}
  462. end;
  463. end;
  464. exit;
  465. end;
  466. { real open call }
  467. FileRec(f).Handle := _open(p,oflags,438);
  468. //WriteLn ('_open (',p,') liefert ',ErrNo, 'Handle: ',FileRec(f).Handle);
  469. // errno does not seem to be set on succsess ??
  470. IF FileRec(f).Handle < 0 THEN
  471. if (ErrNo=Sys_EROFS) and ((OFlags and O_RDWR)<>0) then
  472. begin // i.e. for cd-rom
  473. Oflags:=Oflags and not(O_RDWR);
  474. FileRec(f).Handle := _open(p,oflags,438);
  475. end;
  476. IF FileRec(f).Handle < 0 THEN
  477. Errno2Inoutres
  478. ELSE
  479. InOutRes := 0;
  480. End;
  481. function do_isdevice(handle:longint):boolean;
  482. begin
  483. do_isdevice := (_isatty (handle) > 0);
  484. end;
  485. {*****************************************************************************
  486. UnTyped File Handling
  487. *****************************************************************************}
  488. {$i file.inc}
  489. {*****************************************************************************
  490. Typed File Handling
  491. *****************************************************************************}
  492. {$i typefile.inc}
  493. {*****************************************************************************
  494. Text File Handling
  495. *****************************************************************************}
  496. { should we consider #26 as the end of a file ? }
  497. {?? $DEFINE EOF_CTRLZ}
  498. {$i text.inc}
  499. {*****************************************************************************
  500. Directory Handling
  501. *****************************************************************************}
  502. procedure mkdir(const s : string);[IOCheck];
  503. VAR S2 : STRING;
  504. Res: LONGINT;
  505. BEGIN
  506. S2 := S;
  507. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  508. S2 := S2 + #0;
  509. Res := _mkdir (@S2[1]);
  510. IF Res = 0 THEN
  511. InOutRes:=0
  512. ELSE
  513. SetFileError (Res);
  514. END;
  515. procedure rmdir(const s : string);[IOCheck];
  516. VAR S2 : STRING;
  517. Res: LONGINT;
  518. BEGIN
  519. S2 := S;
  520. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  521. S2 := S2 + #0;
  522. Res := _rmdir (@S2[1]);
  523. IF Res = 0 THEN
  524. InOutRes:=0
  525. ELSE
  526. SetFileError (Res);
  527. end;
  528. procedure chdir(const s : string);[IOCheck];
  529. VAR S2 : STRING;
  530. Res: LONGINT;
  531. begin
  532. S2 := S;
  533. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  534. S2 := S2 + #0;
  535. Res := _chdir (@S2[1]);
  536. IF Res = 0 THEN
  537. InOutRes:=0
  538. ELSE
  539. SetFileError (Res);
  540. end;
  541. procedure getdir(drivenr : byte;var dir : shortstring);
  542. VAR P : ARRAY [0..255] OF CHAR;
  543. Len: LONGINT;
  544. begin
  545. P[0] := #0;
  546. _getcwd (@P, SIZEOF (P));
  547. Len := _strlen (P);
  548. IF Len > 0 THEN
  549. BEGIN
  550. Move (P, dir[1], Len);
  551. BYTE(dir[0]) := Len;
  552. END ELSE
  553. InOutRes := 1;
  554. end;
  555. {*****************************************************************************
  556. Thread Handling
  557. *****************************************************************************}
  558. procedure InitFPU;assembler;
  559. asm
  560. fninit
  561. fldcw fpucw
  562. end;
  563. { if return-value is <> 0, netware shows the message
  564. Unload Anyway ?
  565. To Disable unload at all, SetNLMDontUnloadFlag can be used on
  566. Netware >= 4.0 }
  567. function CheckFunction : longint; CDECL; [public,alias: 'FPC_NW_CHECKFUNCTION'];
  568. var oldTG:longint;
  569. oldPtr: pointer;
  570. begin
  571. if assigned (NetwareCheckFunction) then
  572. begin
  573. { this function is called without clib context, to allow clib
  574. calls, we set the thread group id before calling the
  575. user-function }
  576. oldTG := _SetThreadGroupID (NetwareMainThreadGroupID);
  577. { to allow use of threadvars, we simply set the threadvar-memory
  578. from the main thread }
  579. if assigned (SetThreadDataAreaPtr) then
  580. oldPtr := SetThreadDataAreaPtr (NIL); { nil means main threadvars }
  581. result := 0;
  582. NetwareCheckFunction (result);
  583. if assigned (SetThreadDataAreaPtr) then
  584. SetThreadDataAreaPtr (oldPtr);
  585. _SetThreadGroupID (oldTG);
  586. end else
  587. result := 0;
  588. end;
  589. {$ifdef StdErrToConsole}
  590. var ConsoleBuff : array [0..512] of char;
  591. Function ConsoleWrite(Var F: TextRec): Integer;
  592. var
  593. i : longint;
  594. Begin
  595. if F.BufPos>0 then
  596. begin
  597. if F.BufPos>sizeof(ConsoleBuff)-1 then
  598. i:=sizeof(ConsoleBuff)-1
  599. else
  600. i:=F.BufPos;
  601. Move(F.BufPtr^,ConsoleBuff,i);
  602. ConsoleBuff[i] := #0;
  603. ConsolePrintf(@ConsoleBuff[0]);
  604. end;
  605. F.BufPos:=0;
  606. ConsoleWrite := 0;
  607. End;
  608. Function ConsoleClose(Var F: TextRec): Integer;
  609. begin
  610. ConsoleClose:=0;
  611. end;
  612. Function ConsoleOpen(Var F: TextRec): Integer;
  613. Begin
  614. TextRec(F).InOutFunc:=@ConsoleWrite;
  615. TextRec(F).FlushFunc:=@ConsoleWrite;
  616. TextRec(F).CloseFunc:=@ConsoleClose;
  617. ConsoleOpen:=0;
  618. End;
  619. procedure AssignStdErrConsole(Var T: Text);
  620. begin
  621. Assign(T,'');
  622. TextRec(T).OpenFunc:=@ConsoleOpen;
  623. Rewrite(T);
  624. end;
  625. {$endif}
  626. { this will be called if the nlm is unloaded. It will NOT be
  627. called if the program exits i.e. with halt.
  628. Halt (or _exit) can not be called from this callback procedure }
  629. procedure TermSigHandler (Sig:longint); CDecl;
  630. var oldTG : longint;
  631. oldPtr: pointer;
  632. begin
  633. oldTG := _SetThreadGroupID (NetwareMainThreadGroupID); { this is only needed for nw 3.11 }
  634. { _GetThreadDataAreaPtr will not be valid because the signal
  635. handler is called by netware with a differnt thread. To avoid
  636. problems in the exit routines, we set the data of the main thread
  637. here }
  638. if assigned (SetThreadDataAreaPtr) then
  639. oldPtr := SetThreadDataAreaPtr (NIL); { nil means main thread }
  640. SigTermHandlerActive := true; { to avoid that system_exit calls _exit }
  641. do_exit; { calls finalize units }
  642. if assigned (SetThreadDataAreaPtr) then
  643. SetThreadDataAreaPtr (oldPtr);
  644. _SetThreadGroupID (oldTG);
  645. end;
  646. procedure SysInitStdIO;
  647. begin
  648. { Setup stdin, stdout and stderr }
  649. StdInputHandle := _fileno (LONGINT (_GetStdIn^)); // GetStd** returns **FILE !
  650. StdOutputHandle:= _fileno (LONGINT (_GetStdOut^));
  651. StdErrorHandle := _fileno (LONGINT (_GetStdErr^));
  652. OpenStdIO(Input,fmInput,StdInputHandle);
  653. OpenStdIO(Output,fmOutput,StdOutputHandle);
  654. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  655. {$ifdef StdErrToConsole}
  656. AssignStdErrConsole(StdErr);
  657. {$else}
  658. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  659. {$endif}
  660. end;
  661. {*****************************************************************************
  662. SystemUnit Initialization
  663. *****************************************************************************}
  664. Begin
  665. StackBottom := SPtr - StackLength;
  666. SigTermHandlerActive := false;
  667. NetwareCheckFunction := nil;
  668. NetwareMainThreadGroupID := _GetThreadGroupID;
  669. _Signal (_SIGTERM, @TermSigHandler);
  670. { Setup heap }
  671. InitHeap;
  672. SysInitExceptions;
  673. { Reset IO Error }
  674. InOutRes:=0;
  675. SysInitStdIO;
  676. {Delphi Compatible}
  677. IsLibrary := FALSE;
  678. IsConsole := TRUE;
  679. ExitCode := 0;
  680. {$ifdef HASVARIANT}
  681. initvariantmanager;
  682. {$endif HASVARIANT}
  683. End.
  684. {
  685. $Log$
  686. Revision 1.19 2003-10-17 22:12:02 olle
  687. * changed i386 to cpui386
  688. Revision 1.18 2003/09/27 11:52:35 peter
  689. * sbrk returns pointer
  690. Revision 1.17 2003/03/25 18:17:54 armin
  691. * support for fcl, support for linking without debug info
  692. * renamed winsock2 to winsock for win32 compatinility
  693. * new sockets unit for netware
  694. * changes for compiler warnings
  695. Revision 1.16 2003/02/15 19:12:54 armin
  696. * changes for new threadvar support
  697. Revision 1.15 2002/10/13 09:28:45 florian
  698. + call to initvariantmanager inserted
  699. Revision 1.14 2002/09/07 16:01:21 peter
  700. * old logs removed and tabs fixed
  701. Revision 1.13 2002/07/01 16:29:05 peter
  702. * sLineBreak changed to normal constant like Kylix
  703. Revision 1.12 2002/04/15 18:47:34 carl
  704. + reinstate novell stack checking
  705. Revision 1.11 2002/04/12 17:40:11 carl
  706. + generic stack checking
  707. Revision 1.10 2002/04/01 15:20:08 armin
  708. + unload module no longer shows: Module did not release...
  709. + check-function will no longer be removed when smartlink is on
  710. Revision 1.9 2002/04/01 10:47:31 armin
  711. makefile.fpc for netware
  712. stderr to netware console
  713. free all memory (threadvars and heap) to avoid error message while unloading nlm
  714. Revision 1.8 2002/03/30 09:09:47 armin
  715. + support check-function for netware
  716. Revision 1.7 2002/03/17 17:57:33 armin
  717. + threads and winsock2 implemented
  718. }