system.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  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 i386}
  20. {$define Set_i386_Exception_handler}
  21. {$endif i386}
  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 -1 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):longint;
  202. var P,P2 : POINTER;
  203. begin
  204. P := _malloc (size);
  205. if P = nil then
  206. Sbrk := -1
  207. else begin
  208. Sbrk := LONGINT (P);
  209. if HeapSbrkBlockList = nil then
  210. begin
  211. Pointer (HeapSbrkBlockList) := _malloc (sizeof (HeapSbrkBlockList^));
  212. if HeapSbrkBlockList = nil then
  213. begin
  214. _free (P);
  215. Sbrk := -1;
  216. exit;
  217. end;
  218. fillchar (HeapSbrkBlockList^,sizeof(HeapSbrkBlockList^),0);
  219. HeapSbrkAllocated := HeapInitialMaxBlocks;
  220. end;
  221. if (HeapSbrkLastUsed = HeapSbrkAllocated) then
  222. begin { grow }
  223. p2 := _realloc (HeapSbrkBlockList, HeapSbrkAllocated + HeapInitialMaxBlocks);
  224. if p2 = nil then
  225. begin
  226. _free (P);
  227. Sbrk := -1;
  228. exit;
  229. end;
  230. inc (HeapSbrkAllocated, HeapInitialMaxBlocks);
  231. end;
  232. inc (HeapSbrkLastUsed);
  233. HeapSbrkBlockList^[HeapSbrkLastUsed] := P;
  234. end;
  235. end;
  236. procedure FreeSbrkMem;
  237. var i : longint;
  238. begin
  239. if HeapSbrkBlockList <> nil then
  240. begin
  241. for i := 1 to HeapSbrkLastUsed do
  242. _free (HeapSbrkBlockList^[i]);
  243. _free (HeapSbrkBlockList);
  244. HeapSbrkAllocated := 0;
  245. HeapSbrkLastUsed := 0;
  246. HeapSbrkBlockList := nil;
  247. end;
  248. end;
  249. { include standard heap management }
  250. {$I heap.inc}
  251. {****************************************************************************
  252. Low level File Routines
  253. All these functions can set InOutRes on errors
  254. ****************************************************************************}
  255. PROCEDURE NW2PASErr (Err : LONGINT);
  256. BEGIN
  257. if Err = 0 then { Else it will go through all the cases }
  258. exit;
  259. case Err of
  260. Sys_ENFILE,
  261. Sys_EMFILE : Inoutres:=4;
  262. Sys_ENOENT : Inoutres:=2;
  263. Sys_EBADF : Inoutres:=6;
  264. Sys_ENOMEM,
  265. Sys_EFAULT : Inoutres:=217;
  266. Sys_EINVAL : Inoutres:=218;
  267. Sys_EPIPE,
  268. Sys_EINTR,
  269. Sys_EIO,
  270. Sys_EAGAIN,
  271. Sys_ENOSPC : Inoutres:=101;
  272. Sys_ENAMETOOLONG,
  273. Sys_ELOOP,
  274. Sys_ENOTDIR : Inoutres:=3;
  275. Sys_EROFS,
  276. Sys_EEXIST,
  277. Sys_EACCES : Inoutres:=5;
  278. Sys_EBUSY : Inoutres:=162;
  279. end;
  280. END;
  281. FUNCTION errno : LONGINT;
  282. BEGIN
  283. errno := __get_errno_ptr^;
  284. END;
  285. PROCEDURE Errno2Inoutres;
  286. BEGIN
  287. NW2PASErr (errno);
  288. END;
  289. PROCEDURE SetFileError (VAR Err : LONGINT);
  290. BEGIN
  291. IF Err >= 0 THEN
  292. InOutRes := 0
  293. ELSE
  294. BEGIN
  295. Err := errno;
  296. NW2PASErr (Err);
  297. Err := 0;
  298. END;
  299. END;
  300. { close a file from the handle value }
  301. procedure do_close(handle : longint);
  302. VAR res : LONGINT;
  303. begin
  304. res := _close (handle);
  305. IF res <> 0 THEN
  306. SetFileError (res)
  307. ELSE
  308. InOutRes := 0;
  309. end;
  310. procedure do_erase(p : pchar);
  311. VAR res : LONGINT;
  312. begin
  313. res := _unlink (p);
  314. IF Res < 0 THEN
  315. SetFileError (res)
  316. ELSE
  317. InOutRes := 0;
  318. end;
  319. procedure do_rename(p1,p2 : pchar);
  320. VAR res : LONGINT;
  321. begin
  322. res := _rename (p1,p2);
  323. IF Res < 0 THEN
  324. SetFileError (res)
  325. ELSE
  326. InOutRes := 0
  327. end;
  328. function do_write(h,addr,len : longint) : longint;
  329. VAR res : LONGINT;
  330. begin
  331. res := _write (h,POINTER(addr),len);
  332. IF res > 0 THEN
  333. InOutRes := 0
  334. ELSE
  335. SetFileError (res);
  336. do_write := res;
  337. end;
  338. function do_read(h,addr,len : longint) : longint;
  339. VAR res : LONGINT;
  340. begin
  341. res := _read (h,POINTER(addr),len);
  342. IF res > 0 THEN
  343. InOutRes := 0
  344. ELSE
  345. SetFileError (res);
  346. do_read := res;
  347. end;
  348. function do_filepos(handle : longint) : longint;
  349. VAR res : LONGINT;
  350. begin
  351. InOutRes:=1;
  352. res := _tell (handle);
  353. IF res < 0 THEN
  354. SetFileError (res)
  355. ELSE
  356. InOutRes := 0;
  357. do_filepos := res;
  358. end;
  359. CONST SEEK_SET = 0; // Seek from beginning of file.
  360. SEEK_CUR = 1; // Seek from current position.
  361. SEEK_END = 2; // Seek from end of file.
  362. procedure do_seek(handle,pos : longint);
  363. VAR res : LONGINT;
  364. begin
  365. res := _lseek (handle,pos, SEEK_SET);
  366. IF res >= 0 THEN
  367. InOutRes := 0
  368. ELSE
  369. SetFileError (res);
  370. end;
  371. function do_seekend(handle:longint):longint;
  372. VAR res : LONGINT;
  373. begin
  374. res := _lseek (handle,0, SEEK_END);
  375. IF res >= 0 THEN
  376. InOutRes := 0
  377. ELSE
  378. SetFileError (res);
  379. do_seekend := res;
  380. end;
  381. function do_filesize(handle : longint) : longint;
  382. VAR res : LONGINT;
  383. begin
  384. res := _filelength (handle);
  385. IF res < 0 THEN
  386. BEGIN
  387. SetFileError (Res);
  388. do_filesize := -1;
  389. END ELSE
  390. BEGIN
  391. InOutRes := 0;
  392. do_filesize := res;
  393. END;
  394. end;
  395. { truncate at a given position }
  396. procedure do_truncate (handle,pos:longint);
  397. VAR res : LONGINT;
  398. begin
  399. res := _chsize (handle,pos);
  400. IF res <> 0 THEN
  401. SetFileError (res)
  402. ELSE
  403. InOutRes := 0;
  404. end;
  405. // mostly stolen from syslinux
  406. procedure do_open(var f;p:pchar;flags:longint);
  407. {
  408. filerec and textrec have both handle and mode as the first items so
  409. they could use the same routine for opening/creating.
  410. when (flags and $10) the file will be append
  411. when (flags and $100) the file will be truncate/rewritten
  412. when (flags and $1000) there is no check for close (needed for textfiles)
  413. }
  414. var
  415. oflags : longint;
  416. Begin
  417. { close first if opened }
  418. if ((flags and $10000)=0) then
  419. begin
  420. case FileRec(f).mode of
  421. fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
  422. fmclosed : ;
  423. else
  424. begin
  425. inoutres:=102; {not assigned}
  426. exit;
  427. end;
  428. end;
  429. end;
  430. { reset file Handle }
  431. FileRec(f).Handle:=UnusedHandle;
  432. { We do the conversion of filemodes here, concentrated on 1 place }
  433. case (flags and 3) of
  434. 0 : begin
  435. oflags := O_RDONLY;
  436. filerec(f).mode := fminput;
  437. end;
  438. 1 : begin
  439. oflags := O_WRONLY;
  440. filerec(f).mode := fmoutput;
  441. end;
  442. 2 : begin
  443. oflags := O_RDWR;
  444. filerec(f).mode := fminout;
  445. end;
  446. end;
  447. if (flags and $1000)=$1000 then
  448. oflags:=oflags or (O_CREAT or O_TRUNC)
  449. else
  450. if (flags and $100)=$100 then
  451. oflags:=oflags or (O_APPEND);
  452. { empty name is special }
  453. if p[0]=#0 then
  454. begin
  455. case FileRec(f).mode of
  456. fminput :
  457. FileRec(f).Handle:=StdInputHandle;
  458. fminout, { this is set by rewrite }
  459. fmoutput :
  460. FileRec(f).Handle:=StdOutputHandle;
  461. fmappend :
  462. begin
  463. FileRec(f).Handle:=StdOutputHandle;
  464. FileRec(f).mode:=fmoutput; {fool fmappend}
  465. end;
  466. end;
  467. exit;
  468. end;
  469. { real open call }
  470. FileRec(f).Handle := _open(p,oflags,438);
  471. //WriteLn ('_open (',p,') liefert ',ErrNo, 'Handle: ',FileRec(f).Handle);
  472. // errno does not seem to be set on succsess ??
  473. IF FileRec(f).Handle < 0 THEN
  474. if (ErrNo=Sys_EROFS) and ((OFlags and O_RDWR)<>0) then
  475. begin // i.e. for cd-rom
  476. Oflags:=Oflags and not(O_RDWR);
  477. FileRec(f).Handle := _open(p,oflags,438);
  478. end;
  479. IF FileRec(f).Handle < 0 THEN
  480. Errno2Inoutres
  481. ELSE
  482. InOutRes := 0;
  483. End;
  484. function do_isdevice(handle:longint):boolean;
  485. begin
  486. do_isdevice := (_isatty (handle) > 0);
  487. end;
  488. {*****************************************************************************
  489. UnTyped File Handling
  490. *****************************************************************************}
  491. {$i file.inc}
  492. {*****************************************************************************
  493. Typed File Handling
  494. *****************************************************************************}
  495. {$i typefile.inc}
  496. {*****************************************************************************
  497. Text File Handling
  498. *****************************************************************************}
  499. { should we consider #26 as the end of a file ? }
  500. {?? $DEFINE EOF_CTRLZ}
  501. {$i text.inc}
  502. {*****************************************************************************
  503. Directory Handling
  504. *****************************************************************************}
  505. procedure mkdir(const s : string);[IOCheck];
  506. VAR S2 : STRING;
  507. Res: LONGINT;
  508. BEGIN
  509. S2 := S;
  510. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  511. S2 := S2 + #0;
  512. Res := _mkdir (@S2[1]);
  513. IF Res = 0 THEN
  514. InOutRes:=0
  515. ELSE
  516. SetFileError (Res);
  517. END;
  518. procedure rmdir(const s : string);[IOCheck];
  519. VAR S2 : STRING;
  520. Res: LONGINT;
  521. BEGIN
  522. S2 := S;
  523. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  524. S2 := S2 + #0;
  525. Res := _rmdir (@S2[1]);
  526. IF Res = 0 THEN
  527. InOutRes:=0
  528. ELSE
  529. SetFileError (Res);
  530. end;
  531. procedure chdir(const s : string);[IOCheck];
  532. VAR S2 : STRING;
  533. Res: LONGINT;
  534. begin
  535. S2 := S;
  536. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  537. S2 := S2 + #0;
  538. Res := _chdir (@S2[1]);
  539. IF Res = 0 THEN
  540. InOutRes:=0
  541. ELSE
  542. SetFileError (Res);
  543. end;
  544. procedure getdir(drivenr : byte;var dir : shortstring);
  545. VAR P : ARRAY [0..255] OF CHAR;
  546. Len: LONGINT;
  547. begin
  548. P[0] := #0;
  549. _getcwd (@P, SIZEOF (P));
  550. Len := _strlen (P);
  551. IF Len > 0 THEN
  552. BEGIN
  553. Move (P, dir[1], Len);
  554. BYTE(dir[0]) := Len;
  555. END ELSE
  556. InOutRes := 1;
  557. end;
  558. {*****************************************************************************
  559. Thread Handling
  560. *****************************************************************************}
  561. procedure InitFPU;assembler;
  562. asm
  563. fninit
  564. fldcw fpucw
  565. end;
  566. { if return-value is <> 0, netware shows the message
  567. Unload Anyway ?
  568. To Disable unload at all, SetNLMDontUnloadFlag can be used on
  569. Netware >= 4.0 }
  570. function CheckFunction : longint; CDECL; [public,alias: 'FPC_NW_CHECKFUNCTION'];
  571. var oldTG:longint;
  572. oldPtr: pointer;
  573. begin
  574. if assigned (NetwareCheckFunction) then
  575. begin
  576. { this function is called without clib context, to allow clib
  577. calls, we set the thread group id before calling the
  578. user-function }
  579. oldTG := _SetThreadGroupID (NetwareMainThreadGroupID);
  580. { to allow use of threadvars, we simply set the threadvar-memory
  581. from the main thread }
  582. if assigned (SetThreadDataAreaPtr) then
  583. oldPtr := SetThreadDataAreaPtr (NIL); { nil means main threadvars }
  584. result := 0;
  585. NetwareCheckFunction (result);
  586. if assigned (SetThreadDataAreaPtr) then
  587. SetThreadDataAreaPtr (oldPtr);
  588. _SetThreadGroupID (oldTG);
  589. end else
  590. result := 0;
  591. end;
  592. {$ifdef StdErrToConsole}
  593. var ConsoleBuff : array [0..512] of char;
  594. Function ConsoleWrite(Var F: TextRec): Integer;
  595. var
  596. i : longint;
  597. Begin
  598. if F.BufPos>0 then
  599. begin
  600. if F.BufPos>sizeof(ConsoleBuff)-1 then
  601. i:=sizeof(ConsoleBuff)-1
  602. else
  603. i:=F.BufPos;
  604. Move(F.BufPtr^,ConsoleBuff,i);
  605. ConsoleBuff[i] := #0;
  606. ConsolePrintf(@ConsoleBuff[0]);
  607. end;
  608. F.BufPos:=0;
  609. ConsoleWrite := 0;
  610. End;
  611. Function ConsoleClose(Var F: TextRec): Integer;
  612. begin
  613. ConsoleClose:=0;
  614. end;
  615. Function ConsoleOpen(Var F: TextRec): Integer;
  616. Begin
  617. TextRec(F).InOutFunc:=@ConsoleWrite;
  618. TextRec(F).FlushFunc:=@ConsoleWrite;
  619. TextRec(F).CloseFunc:=@ConsoleClose;
  620. ConsoleOpen:=0;
  621. End;
  622. procedure AssignStdErrConsole(Var T: Text);
  623. begin
  624. Assign(T,'');
  625. TextRec(T).OpenFunc:=@ConsoleOpen;
  626. Rewrite(T);
  627. end;
  628. {$endif}
  629. { this will be called if the nlm is unloaded. It will NOT be
  630. called if the program exits i.e. with halt.
  631. Halt (or _exit) can not be called from this callback procedure }
  632. procedure TermSigHandler (Sig:longint); CDecl;
  633. var oldTG : longint;
  634. oldPtr: pointer;
  635. begin
  636. oldTG := _SetThreadGroupID (NetwareMainThreadGroupID); { this is only needed for nw 3.11 }
  637. { _GetThreadDataAreaPtr will not be valid because the signal
  638. handler is called by netware with a differnt thread. To avoid
  639. problems in the exit routines, we set the data of the main thread
  640. here }
  641. if assigned (SetThreadDataAreaPtr) then
  642. oldPtr := SetThreadDataAreaPtr (NIL); { nil means main thread }
  643. SigTermHandlerActive := true; { to avoid that system_exit calls _exit }
  644. do_exit; { calls finalize units }
  645. if assigned (SetThreadDataAreaPtr) then
  646. SetThreadDataAreaPtr (oldPtr);
  647. _SetThreadGroupID (oldTG);
  648. end;
  649. procedure SysInitStdIO;
  650. begin
  651. { Setup stdin, stdout and stderr }
  652. StdInputHandle := _fileno (LONGINT (_GetStdIn^)); // GetStd** returns **FILE !
  653. StdOutputHandle:= _fileno (LONGINT (_GetStdOut^));
  654. StdErrorHandle := _fileno (LONGINT (_GetStdErr^));
  655. OpenStdIO(Input,fmInput,StdInputHandle);
  656. OpenStdIO(Output,fmOutput,StdOutputHandle);
  657. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  658. {$ifdef StdErrToConsole}
  659. AssignStdErrConsole(StdErr);
  660. {$else}
  661. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  662. {$endif}
  663. end;
  664. {*****************************************************************************
  665. SystemUnit Initialization
  666. *****************************************************************************}
  667. Begin
  668. StackBottom := SPtr - StackLength;
  669. SigTermHandlerActive := false;
  670. NetwareCheckFunction := nil;
  671. NetwareMainThreadGroupID := _GetThreadGroupID;
  672. _Signal (_SIGTERM, @TermSigHandler);
  673. { Setup heap }
  674. InitHeap;
  675. SysInitExceptions;
  676. { Reset IO Error }
  677. InOutRes:=0;
  678. SysInitStdIO;
  679. {Delphi Compatible}
  680. IsLibrary := FALSE;
  681. IsConsole := TRUE;
  682. ExitCode := 0;
  683. {$ifdef HASVARIANT}
  684. initvariantmanager;
  685. {$endif HASVARIANT}
  686. End.
  687. {
  688. $Log$
  689. Revision 1.17 2003-03-25 18:17:54 armin
  690. * support for fcl, support for linking without debug info
  691. * renamed winsock2 to winsock for win32 compatinility
  692. * new sockets unit for netware
  693. * changes for compiler warnings
  694. Revision 1.16 2003/02/15 19:12:54 armin
  695. * changes for new threadvar support
  696. Revision 1.15 2002/10/13 09:28:45 florian
  697. + call to initvariantmanager inserted
  698. Revision 1.14 2002/09/07 16:01:21 peter
  699. * old logs removed and tabs fixed
  700. Revision 1.13 2002/07/01 16:29:05 peter
  701. * sLineBreak changed to normal constant like Kylix
  702. Revision 1.12 2002/04/15 18:47:34 carl
  703. + reinstate novell stack checking
  704. Revision 1.11 2002/04/12 17:40:11 carl
  705. + generic stack checking
  706. Revision 1.10 2002/04/01 15:20:08 armin
  707. + unload module no longer shows: Module did not release...
  708. + check-function will no longer be removed when smartlink is on
  709. Revision 1.9 2002/04/01 10:47:31 armin
  710. makefile.fpc for netware
  711. stderr to netware console
  712. free all memory (threadvars and heap) to avoid error message while unloading nlm
  713. Revision 1.8 2002/03/30 09:09:47 armin
  714. + support check-function for netware
  715. Revision 1.7 2002/03/17 17:57:33 armin
  716. + threads and winsock2 implemented
  717. }