system.pp 14 KB

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