system.pp 13 KB

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