system.pp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  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. {$ifdef SYSTEMDEBUG}
  16. {$define SYSTEMEXCEPTIONDEBUG}
  17. {$endif SYSTEMDEBUG}
  18. {$ifdef i386}
  19. {$define Set_i386_Exception_handler}
  20. {$endif i386}
  21. { include system-independent routine headers }
  22. {$I systemh.inc}
  23. { include heap support headers }
  24. {Why the hell do i have to define that ???
  25. otherwise FPC_FREEMEM expects 2 parameters but the compiler only
  26. puhes the address}
  27. { DEFINE NEWMM}
  28. { I heaph.inc}
  29. {Platform specific information}
  30. const
  31. LineEnding = #13#10;
  32. LFNSupport = false; { ??? - that's how it was declared in dos.pp! }
  33. DirectorySeparator = '\';
  34. DriveSeparator = ':';
  35. PathSeparator = ';';
  36. { FileNameCaseSensitive is defined separately below!!! }
  37. type
  38. { the fields of this record are os dependent }
  39. { and they shouldn't be used in a program }
  40. { only the type TCriticalSection is important }
  41. TRTLCriticalSection = packed record
  42. SemaHandle : LONGINT;
  43. SemaIsOpen : BOOLEAN;
  44. end;
  45. { include threading stuff }
  46. {$i threadh.inc}
  47. { include heap support headers }
  48. {$I heaph.inc}
  49. CONST
  50. { Default filehandles }
  51. UnusedHandle : longint = -1;
  52. StdInputHandle : longint = 0;
  53. StdOutputHandle : longint = 0;
  54. StdErrorHandle : longint = 0;
  55. FileNameCaseSensitive : boolean = false;
  56. sLineBreak : STRING = LineEnding;
  57. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  58. VAR
  59. ArgC : INTEGER;
  60. ArgV : ppchar;
  61. CONST
  62. envp : ppchar = nil; {dummy to make heaptrc happy}
  63. implementation
  64. { ?? why does this not work ?? DEFINE FPC_SYSTEM_HAS_MOVE}
  65. {procedure move (const source; var dest; count : longint);
  66. begin
  67. _memcpy (@dest, @source, count);
  68. end;}
  69. { include system independent routines }
  70. {$I system.inc}
  71. { some declarations for Netware API calls }
  72. {$I nwsys.inc}
  73. {$I errno.inc}
  74. procedure setup_arguments;
  75. begin
  76. end;
  77. procedure setup_environment;
  78. begin
  79. end;
  80. procedure PASCALMAIN;external name 'PASCALMAIN';
  81. procedure fpc_do_exit;external name 'FPC_DO_EXIT';
  82. {*****************************************************************************
  83. Startup
  84. *****************************************************************************}
  85. PROCEDURE _nlm_main (_ArgC : LONGINT; _ArgV : ppchar); CDECL; [public,alias: '_nlm_main'];
  86. BEGIN
  87. ArgC := _ArgC;
  88. ArgV := _ArgV;
  89. PASCALMAIN;
  90. END;
  91. {$ifdef MT}
  92. PROCEDURE CloseAllRemainingSemaphores; FORWARD;
  93. {$endif}
  94. {*****************************************************************************
  95. System Dependent Exit code
  96. *****************************************************************************}
  97. Procedure system_exit;
  98. begin
  99. {ConsolePrintf ('system_exit called'#13#10,0);}
  100. {$ifdef MT}
  101. CloseAllRemainingSemaphores;
  102. {$endif}
  103. _exit (ExitCode);
  104. end;
  105. {*****************************************************************************
  106. Stack check code
  107. *****************************************************************************}
  108. procedure int_stackcheck(stack_size:longint);[public,alias:'FPC_STACKCHECK'];
  109. {
  110. called when trying to get local stack if the compiler directive $S
  111. is set this function must preserve esi !!!! because esi is set by
  112. the calling proc for methods it must preserve all registers !!
  113. With a 2048 byte safe area used to write to StdIo without crossing
  114. the stack boundary
  115. }
  116. begin
  117. IF _stackavail > stack_size + 2048 THEN EXIT;
  118. HandleError (202);
  119. end;
  120. {*****************************************************************************
  121. ParamStr/Randomize
  122. *****************************************************************************}
  123. { number of args }
  124. function paramcount : longint;
  125. begin
  126. paramcount := argc - 1;
  127. end;
  128. { argument number l }
  129. function paramstr(l : longint) : string;
  130. begin
  131. if (l>=0) and (l+1<=argc) then
  132. paramstr:=strpas(argv[l])
  133. else
  134. paramstr:='';
  135. end;
  136. { set randseed to a new pseudo random value }
  137. procedure randomize;
  138. begin
  139. randseed := _time (NIL);
  140. end;
  141. {*****************************************************************************
  142. Heap Management
  143. *****************************************************************************}
  144. { first address of heap }
  145. function getheapstart:pointer;
  146. assembler;
  147. asm
  148. leal HEAP,%eax
  149. end ['EAX'];
  150. { current length of heap }
  151. function getheapsize:longint;
  152. assembler;
  153. asm
  154. movl HEAPSIZE,%eax
  155. end ['EAX'];
  156. { function to allocate size bytes more for the program }
  157. { must return the first address of new data space or -1 if fail }
  158. FUNCTION Sbrk(size : longint):longint;
  159. VAR P : POINTER;
  160. BEGIN
  161. P := _malloc (size);
  162. IF P = NIL THEN
  163. Sbrk := -1
  164. ELSE
  165. Sbrk := LONGINT (P);
  166. END;
  167. { include standard heap management }
  168. {$I heap.inc}
  169. {****************************************************************************
  170. Low level File Routines
  171. All these functions can set InOutRes on errors
  172. ****************************************************************************}
  173. PROCEDURE NW2PASErr (Err : LONGINT);
  174. BEGIN
  175. if Err = 0 then { Else it will go through all the cases }
  176. exit;
  177. case Err of
  178. Sys_ENFILE,
  179. Sys_EMFILE : Inoutres:=4;
  180. Sys_ENOENT : Inoutres:=2;
  181. Sys_EBADF : Inoutres:=6;
  182. Sys_ENOMEM,
  183. Sys_EFAULT : Inoutres:=217;
  184. Sys_EINVAL : Inoutres:=218;
  185. Sys_EPIPE,
  186. Sys_EINTR,
  187. Sys_EIO,
  188. Sys_EAGAIN,
  189. Sys_ENOSPC : Inoutres:=101;
  190. Sys_ENAMETOOLONG,
  191. Sys_ELOOP,
  192. Sys_ENOTDIR : Inoutres:=3;
  193. Sys_EROFS,
  194. Sys_EEXIST,
  195. Sys_EACCES : Inoutres:=5;
  196. Sys_EBUSY : Inoutres:=162;
  197. end;
  198. END;
  199. FUNCTION errno : LONGINT;
  200. BEGIN
  201. errno := __get_errno_ptr^;
  202. END;
  203. PROCEDURE Errno2Inoutres;
  204. BEGIN
  205. NW2PASErr (errno);
  206. END;
  207. PROCEDURE SetFileError (VAR Err : LONGINT);
  208. BEGIN
  209. IF Err >= 0 THEN
  210. InOutRes := 0
  211. ELSE
  212. BEGIN
  213. Err := errno;
  214. NW2PASErr (Err);
  215. Err := 0;
  216. END;
  217. END;
  218. { close a file from the handle value }
  219. procedure do_close(handle : longint);
  220. VAR res : LONGINT;
  221. begin
  222. res := _close (handle);
  223. IF res <> 0 THEN
  224. SetFileError (res)
  225. ELSE
  226. InOutRes := 0;
  227. end;
  228. procedure do_erase(p : pchar);
  229. VAR res : LONGINT;
  230. begin
  231. res := _unlink (p);
  232. IF Res < 0 THEN
  233. SetFileError (res)
  234. ELSE
  235. InOutRes := 0;
  236. end;
  237. procedure do_rename(p1,p2 : pchar);
  238. VAR res : LONGINT;
  239. begin
  240. res := _rename (p1,p2);
  241. IF Res < 0 THEN
  242. SetFileError (res)
  243. ELSE
  244. InOutRes := 0
  245. end;
  246. function do_write(h,addr,len : longint) : longint;
  247. VAR res : LONGINT;
  248. begin
  249. res := _write (h,POINTER(addr),len);
  250. IF res > 0 THEN
  251. InOutRes := 0
  252. ELSE
  253. SetFileError (res);
  254. do_write := res;
  255. end;
  256. function do_read(h,addr,len : longint) : longint;
  257. VAR res : LONGINT;
  258. begin
  259. res := _read (h,POINTER(addr),len);
  260. IF res > 0 THEN
  261. InOutRes := 0
  262. ELSE
  263. SetFileError (res);
  264. do_read := res;
  265. end;
  266. function do_filepos(handle : longint) : longint;
  267. VAR res : LONGINT;
  268. begin
  269. InOutRes:=1;
  270. res := _tell (handle);
  271. IF res < 0 THEN
  272. SetFileError (res)
  273. ELSE
  274. InOutRes := 0;
  275. do_filepos := res;
  276. end;
  277. CONST SEEK_SET = 0; // Seek from beginning of file.
  278. SEEK_CUR = 1; // Seek from current position.
  279. SEEK_END = 2; // Seek from end of file.
  280. procedure do_seek(handle,pos : longint);
  281. VAR res : LONGINT;
  282. begin
  283. res := _lseek (handle,pos, SEEK_SET);
  284. IF res >= 0 THEN
  285. InOutRes := 0
  286. ELSE
  287. SetFileError (res);
  288. end;
  289. function do_seekend(handle:longint):longint;
  290. VAR res : LONGINT;
  291. begin
  292. res := _lseek (handle,0, SEEK_END);
  293. IF res >= 0 THEN
  294. InOutRes := 0
  295. ELSE
  296. SetFileError (res);
  297. do_seekend := res;
  298. end;
  299. function do_filesize(handle : longint) : longint;
  300. VAR res : LONGINT;
  301. begin
  302. res := _filelength (handle);
  303. IF res < 0 THEN
  304. BEGIN
  305. SetFileError (Res);
  306. do_filesize := -1;
  307. END ELSE
  308. BEGIN
  309. InOutRes := 0;
  310. do_filesize := res;
  311. END;
  312. end;
  313. { truncate at a given position }
  314. procedure do_truncate (handle,pos:longint);
  315. VAR res : LONGINT;
  316. begin
  317. res := _chsize (handle,pos);
  318. IF res <> 0 THEN
  319. SetFileError (res)
  320. ELSE
  321. InOutRes := 0;
  322. end;
  323. // mostly stolen from syslinux
  324. procedure do_open(var f;p:pchar;flags:longint);
  325. {
  326. filerec and textrec have both handle and mode as the first items so
  327. they could use the same routine for opening/creating.
  328. when (flags and $10) the file will be append
  329. when (flags and $100) the file will be truncate/rewritten
  330. when (flags and $1000) there is no check for close (needed for textfiles)
  331. }
  332. var
  333. oflags : longint;
  334. Begin
  335. { close first if opened }
  336. if ((flags and $10000)=0) then
  337. begin
  338. case FileRec(f).mode of
  339. fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
  340. fmclosed : ;
  341. else
  342. begin
  343. inoutres:=102; {not assigned}
  344. exit;
  345. end;
  346. end;
  347. end;
  348. { reset file Handle }
  349. FileRec(f).Handle:=UnusedHandle;
  350. { We do the conversion of filemodes here, concentrated on 1 place }
  351. case (flags and 3) of
  352. 0 : begin
  353. oflags := O_RDONLY;
  354. filerec(f).mode := fminput;
  355. end;
  356. 1 : begin
  357. oflags := O_WRONLY;
  358. filerec(f).mode := fmoutput;
  359. end;
  360. 2 : begin
  361. oflags := O_RDWR;
  362. filerec(f).mode := fminout;
  363. end;
  364. end;
  365. if (flags and $1000)=$1000 then
  366. oflags:=oflags or (O_CREAT or O_TRUNC)
  367. else
  368. if (flags and $100)=$100 then
  369. oflags:=oflags or (O_APPEND);
  370. { empty name is special }
  371. if p[0]=#0 then
  372. begin
  373. case FileRec(f).mode of
  374. fminput :
  375. FileRec(f).Handle:=StdInputHandle;
  376. fminout, { this is set by rewrite }
  377. fmoutput :
  378. FileRec(f).Handle:=StdOutputHandle;
  379. fmappend :
  380. begin
  381. FileRec(f).Handle:=StdOutputHandle;
  382. FileRec(f).mode:=fmoutput; {fool fmappend}
  383. end;
  384. end;
  385. exit;
  386. end;
  387. { real open call }
  388. FileRec(f).Handle := _open(p,oflags,438);
  389. //WriteLn ('_open (',p,') liefert ',ErrNo, 'Handle: ',FileRec(f).Handle);
  390. // errno does not seem to be set on succsess ??
  391. IF FileRec(f).Handle < 0 THEN
  392. if (ErrNo=Sys_EROFS) and ((OFlags and O_RDWR)<>0) then
  393. begin // i.e. for cd-rom
  394. Oflags:=Oflags and not(O_RDWR);
  395. FileRec(f).Handle := _open(p,oflags,438);
  396. end;
  397. IF FileRec(f).Handle < 0 THEN
  398. Errno2Inoutres
  399. ELSE
  400. InOutRes := 0;
  401. End;
  402. function do_isdevice(handle:longint):boolean;
  403. begin
  404. do_isdevice := (_isatty (handle) > 0);
  405. end;
  406. {*****************************************************************************
  407. UnTyped File Handling
  408. *****************************************************************************}
  409. {$i file.inc}
  410. {*****************************************************************************
  411. Typed File Handling
  412. *****************************************************************************}
  413. {$i typefile.inc}
  414. {*****************************************************************************
  415. Text File Handling
  416. *****************************************************************************}
  417. { should we consider #26 as the end of a file ? }
  418. {?? $DEFINE EOF_CTRLZ}
  419. {$i text.inc}
  420. {*****************************************************************************
  421. Directory Handling
  422. *****************************************************************************}
  423. procedure mkdir(const s : string);[IOCheck];
  424. VAR S2 : STRING;
  425. Res: LONGINT;
  426. BEGIN
  427. S2 := S;
  428. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  429. S2 := S2 + #0;
  430. Res := _mkdir (@S2[1]);
  431. IF Res = 0 THEN
  432. InOutRes:=0
  433. ELSE
  434. SetFileError (Res);
  435. END;
  436. procedure rmdir(const s : string);[IOCheck];
  437. VAR S2 : STRING;
  438. Res: LONGINT;
  439. BEGIN
  440. S2 := S;
  441. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  442. S2 := S2 + #0;
  443. Res := _rmdir (@S2[1]);
  444. IF Res = 0 THEN
  445. InOutRes:=0
  446. ELSE
  447. SetFileError (Res);
  448. end;
  449. procedure chdir(const s : string);[IOCheck];
  450. VAR S2 : STRING;
  451. Res: LONGINT;
  452. begin
  453. S2 := S;
  454. IF Length (S2) = 255 THEN DEC (BYTE(S2[0]));
  455. S2 := S2 + #0;
  456. Res := _chdir (@S2[1]);
  457. IF Res = 0 THEN
  458. InOutRes:=0
  459. ELSE
  460. SetFileError (Res);
  461. end;
  462. procedure getdir(drivenr : byte;var dir : shortstring);
  463. VAR P : ARRAY [0..255] OF CHAR;
  464. Len: LONGINT;
  465. begin
  466. P[0] := #0;
  467. _getcwd (@P, SIZEOF (P));
  468. Len := _strlen (P);
  469. IF Len > 0 THEN
  470. BEGIN
  471. Move (P, dir[1], Len);
  472. BYTE(dir[0]) := Len;
  473. END ELSE
  474. InOutRes := 1;
  475. end;
  476. {*****************************************************************************
  477. Thread Handling
  478. *****************************************************************************}
  479. const
  480. fpucw : word = $1332;
  481. procedure InitFPU;assembler;
  482. asm
  483. fninit
  484. fldcw fpucw
  485. end;
  486. { include threading stuff, this is os dependend part }
  487. {$I thread.inc}
  488. {*****************************************************************************
  489. SystemUnit Initialization
  490. *****************************************************************************}
  491. Begin
  492. {$ifdef MT}
  493. { the exceptions use threadvars so do this _before_ initexceptions }
  494. AllocateThreadVars;
  495. {$endif MT}
  496. { Setup heap }
  497. InitHeap;
  498. InitExceptions;
  499. { Setup stdin, stdout and stderr }
  500. StdInputHandle := _fileno (LONGINT (_GetStdIn^)); // GetStd** returns **FILE !
  501. StdOutputHandle:= _fileno (LONGINT (_GetStdOut^));
  502. StdErrorHandle := _fileno (LONGINT (_GetStdErr^));
  503. OpenStdIO(Input,fmInput,StdInputHandle);
  504. OpenStdIO(Output,fmOutput,StdOutputHandle);
  505. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  506. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  507. { Setup environment and arguments }
  508. Setup_Environment;
  509. Setup_Arguments;
  510. { Reset IO Error }
  511. InOutRes:=0;
  512. {Delphi Compatible}
  513. IsLibrary := FALSE;
  514. IsConsole := TRUE;
  515. End.
  516. {
  517. $Log$
  518. Revision 1.7 2002-03-17 17:57:33 armin
  519. + threads and winsock2 implemented
  520. Revision 1.5 2001/06/18 14:26:16 jonas
  521. * move platform independent constant declarations after inclusion of
  522. systemh.inc
  523. Revision 1.4 2001/06/13 22:20:11 hajny
  524. + platform specific information
  525. Revision 1.3 2001/04/16 18:39:50 florian
  526. * updates from Armin commited
  527. Revision 1.2 2001/04/11 14:17:00 florian
  528. * added logs, fixed email address of Armin, it is
  529. [email protected]
  530. Revision 1.1 2001/04/11 14:14:12 florian
  531. * initial commit, thanks to Armin Diehl ([email protected])
  532. Revision 1.2 2000/07/13 11:33:56 michael
  533. + removed logs
  534. }