system.pp 13 KB

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