system.pp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2004 by Karoly Balogh for Genesi S.a.r.l.
  5. System unit for MorphOS/PowerPC
  6. Uses parts of the Commodore Amiga/68k port by Carl Eric Codere
  7. and Nils Sjoholm
  8. MorphOS port was done on a free Pegasos II/G4 machine
  9. provided by Genesi S.a.r.l. <www.genesi.lu>
  10. See the file COPYING.FPC, included in this distribution,
  11. for details about the copyright.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. **********************************************************************}
  16. unit {$ifdef VER1_0}SysMorph{$else}System{$endif};
  17. interface
  18. {$define FPC_IS_SYSTEM}
  19. {$I systemh.inc}
  20. type
  21. THandle = LongInt;
  22. {$I heaph.inc}
  23. const
  24. LineEnding = #10;
  25. LFNSupport = True;
  26. DirectorySeparator = '/';
  27. DriveSeparator = ':';
  28. PathSeparator = ';';
  29. const
  30. UnusedHandle : LongInt = -1;
  31. StdInputHandle : LongInt = 0;
  32. StdOutputHandle : LongInt = 0;
  33. StdErrorHandle : LongInt = 0;
  34. FileNameCaseSensitive : Boolean = False;
  35. sLineBreak : string[1] = LineEnding;
  36. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsLF;
  37. BreakOn : Boolean = True;
  38. var
  39. MOS_ExecBase : Pointer; external name '_ExecBase';
  40. MOS_DOSBase : Pointer;
  41. MOS_UtilityBase: Pointer;
  42. MOS_heapPool : Pointer; { pointer for the OS pool for growing the heap }
  43. MOS_origDir : LongInt; { original directory on startup }
  44. MOS_ambMsg : Pointer;
  45. MOS_ConName : PChar ='CON:10/30/620/100/FPC Console Output/AUTO/CLOSE/WAIT';
  46. MOS_ConHandle: LongInt;
  47. argc: LongInt;
  48. argv: PPChar;
  49. envp: PPChar;
  50. implementation
  51. {$I system.inc}
  52. {*****************************************************************************
  53. MorphOS structures
  54. *****************************************************************************}
  55. {$include execd.inc}
  56. {$include timerd.inc}
  57. {$include doslibd.inc}
  58. {*****************************************************************************
  59. MorphOS functions
  60. *****************************************************************************}
  61. { exec.library functions }
  62. {$include execf.inc}
  63. {$include doslibf.inc}
  64. {*****************************************************************************
  65. System Dependent Structures/Consts
  66. *****************************************************************************}
  67. const
  68. CTRL_C = 20; { Error code on CTRL-C press }
  69. {*****************************************************************************
  70. MorphOS File-handling Support Functions
  71. *****************************************************************************}
  72. type
  73. { AmigaOS does not automatically close opened files on exit back to }
  74. { the operating system, therefore as a precuation we close all files }
  75. { manually on exit. }
  76. PFileList = ^TFileList;
  77. TFileList = record { no packed, must be correctly aligned }
  78. handle : LongInt; { Handle to file }
  79. next : PFileList; { Next file in list }
  80. end;
  81. var
  82. MOS_fileList: PFileList; { List pointer to opened files }
  83. { Function to be called at program shutdown, to close all opened files }
  84. procedure CloseList(l: PFileList);
  85. var
  86. tmpNext : PFileList;
  87. tmpHandle : LongInt;
  88. begin
  89. if l=nil then exit;
  90. { First, close all tracked files }
  91. tmpNext:=l^.next;
  92. while tmpNext<>nil do begin
  93. tmpHandle:=tmpNext^.handle;
  94. if (tmpHandle<>StdInputHandle) and (tmpHandle<>StdOutputHandle)
  95. and (tmpHandle<>StdErrorHandle) then begin
  96. dosClose(tmpHandle);
  97. end;
  98. tmpNext:=tmpNext^.next;
  99. end;
  100. { Next, erase the linked list }
  101. while l<>nil do begin
  102. tmpNext:=l;
  103. l:=l^.next;
  104. dispose(tmpNext);
  105. end;
  106. end;
  107. { Function to be called to add a file to the opened file list }
  108. procedure AddToList(var l: PFileList; h: LongInt);
  109. var
  110. p : PFileList;
  111. inList: Boolean;
  112. begin
  113. inList:=False;
  114. if l<>nil then begin
  115. { if there is a valid filelist, search for the value }
  116. { in the list to avoid double additions }
  117. p:=l;
  118. while (p^.next<>nil) and (not inList) do
  119. if p^.next^.handle=h then inList:=True
  120. else p:=p^.next;
  121. p:=nil;
  122. end else begin
  123. { if the list is not yet allocated, allocate it. }
  124. New(l);
  125. l^.next:=nil;
  126. end;
  127. if not inList then begin
  128. New(p);
  129. p^.handle:=h;
  130. p^.next:=l^.next;
  131. l^.next:=p;
  132. end;
  133. end;
  134. { Function to be called to remove a file from the list }
  135. procedure RemoveFromList(var l: PFileList; h: longint);
  136. var
  137. p : PFileList;
  138. inList: Boolean;
  139. begin
  140. if l=nil then exit;
  141. inList:=False;
  142. p:=l;
  143. while (p^.next<>nil) and (not inList) do
  144. if p^.next^.handle=h then inList:=True
  145. else p:=p^.next;
  146. if p^.next<>nil then begin
  147. dispose(p^.next);
  148. p^.next:=p^.next^.next;
  149. end;
  150. end;
  151. {*****************************************************************************
  152. Misc. System Dependent Functions
  153. *****************************************************************************}
  154. procedure haltproc(e:longint);cdecl;external name '_haltproc';
  155. procedure System_exit;
  156. begin
  157. { We must remove the CTRL-C FALG here because halt }
  158. { may call I/O routines, which in turn might call }
  159. { halt, so a recursive stack crash }
  160. if BreakOn then begin
  161. if (SetSignal(0,0) and SIGBREAKF_CTRL_C)<>0 then
  162. SetSignal(0,SIGBREAKF_CTRL_C);
  163. end;
  164. { Closing opened files }
  165. CloseList(MOS_fileList);
  166. if MOS_UtilityBase<>nil then CloseLibrary(MOS_UtilityBase);
  167. if MOS_DOSBase<>nil then CloseLibrary(MOS_DOSBase);
  168. if MOS_heapPool<>nil then DeletePool(MOS_heapPool);
  169. haltproc(ExitCode);
  170. end;
  171. { Converts a MorphOS dos.library error code to a TP compatible error code }
  172. { Based on 1.0.x Amiga RTL }
  173. procedure dosError2InOut(errno: LongInt);
  174. begin
  175. case errno of
  176. ERROR_BAD_NUMBER,
  177. ERROR_ACTION_NOT_KNOWN,
  178. ERROR_NOT_IMPLEMENTED : InOutRes := 1;
  179. ERROR_OBJECT_NOT_FOUND : InOutRes := 2;
  180. ERROR_DIR_NOT_FOUND : InOutRes := 3;
  181. ERROR_DISK_WRITE_PROTECTED : InOutRes := 150;
  182. ERROR_OBJECT_WRONG_TYPE : InOutRes := 151;
  183. ERROR_OBJECT_EXISTS,
  184. ERROR_DELETE_PROTECTED,
  185. ERROR_WRITE_PROTECTED,
  186. ERROR_READ_PROTECTED,
  187. ERROR_OBJECT_IN_USE,
  188. ERROR_DIRECTORY_NOT_EMPTY : InOutRes := 5;
  189. ERROR_NO_MORE_ENTRIES : InOutRes := 18;
  190. ERROR_RENAME_ACROSS_DEVICES : InOutRes := 17;
  191. ERROR_DISK_FULL : InOutRes := 101;
  192. ERROR_INVALID_RESIDENT_LIBRARY : InoutRes := 153;
  193. ERROR_BAD_HUNK : InOutRes := 153;
  194. ERROR_NOT_A_DOS_DISK : InOutRes := 157;
  195. ERROR_NO_DISK,
  196. ERROR_DISK_NOT_VALIDATED,
  197. ERROR_DEVICE_NOT_MOUNTED : InOutRes := 152;
  198. ERROR_SEEK_ERROR : InOutRes := 156;
  199. ERROR_LOCK_COLLISION,
  200. ERROR_LOCK_TIMEOUT,
  201. ERROR_UNLOCK_ERROR,
  202. ERROR_INVALID_LOCK,
  203. ERROR_INVALID_COMPONENT_NAME,
  204. ERROR_BAD_STREAM_NAME,
  205. ERROR_FILE_NOT_OBJECT : InOutRes := 6;
  206. else
  207. InOutres := errno;
  208. end;
  209. end;
  210. { Used for CTRL_C checking in I/O calls }
  211. procedure checkCTRLC;
  212. begin
  213. if BreakOn then begin
  214. if (SetSignal(0,0) And SIGBREAKF_CTRL_C)<>0 then begin
  215. { Clear CTRL-C signal }
  216. SetSignal(0,SIGBREAKF_CTRL_C);
  217. Halt(CTRL_C);
  218. end;
  219. end;
  220. end;
  221. { Generates correct argument array on startup }
  222. procedure GenerateArgs;
  223. var
  224. argvlen : longint;
  225. procedure allocarg(idx,len:longint);
  226. var
  227. i,oldargvlen : longint;
  228. begin
  229. if idx>=argvlen then
  230. begin
  231. oldargvlen:=argvlen;
  232. argvlen:=(idx+8) and (not 7);
  233. sysreallocmem(argv,argvlen*sizeof(pointer));
  234. for i:=oldargvlen to argvlen-1 do
  235. argv[i]:=nil;
  236. end;
  237. { use realloc to reuse already existing memory }
  238. sysreallocmem(argv[idx],len+1);
  239. end;
  240. var
  241. count: word;
  242. start: word;
  243. localindex: word;
  244. p : pchar;
  245. temp : string;
  246. begin
  247. p:=GetArgStr;
  248. argvlen:=0;
  249. { Set argv[0] }
  250. temp:=paramstr(0);
  251. allocarg(0,length(temp));
  252. move(temp[1],argv[0]^,length(temp));
  253. argv[0][length(temp)]:=#0;
  254. { check if we're started from Ambient }
  255. if MOS_ambMsg<>nil then
  256. begin
  257. argc:=0;
  258. exit;
  259. end;
  260. { Handle the other args }
  261. count:=0;
  262. { first index is one }
  263. localindex:=1;
  264. while (p[count]<>#0) do
  265. begin
  266. while (p[count]=' ') or (p[count]=#9) or (p[count]=LineEnding) do inc(count);
  267. start:=count;
  268. while (p[count]<>#0) and (p[count]<>' ') and (p[count]<>#9) and (p[count]<>LineEnding) do inc(count);
  269. if (count-start>0) then
  270. begin
  271. allocarg(localindex,count-start);
  272. move(p[start],argv[localindex]^,count-start);
  273. argv[localindex][count-start]:=#0;
  274. inc(localindex);
  275. end;
  276. end;
  277. argc:=localindex;
  278. end;
  279. function GetProgDir: String;
  280. var
  281. s1 : String;
  282. alock : LongInt;
  283. counter: Byte;
  284. begin
  285. GetProgDir:='';
  286. FillChar(s1,255,#0);
  287. { GetLock of program directory }
  288. alock:=GetProgramDir;
  289. if alock<>0 then begin
  290. if NameFromLock(alock,@s1[1],255) then begin
  291. counter:=1;
  292. while (s1[counter]<>#0) and (counter<>0) do Inc(counter);
  293. s1[0]:=Char(counter-1);
  294. GetProgDir:=s1;
  295. end;
  296. end;
  297. end;
  298. function GetProgramName: String;
  299. { Returns ONLY the program name }
  300. var
  301. s1 : String;
  302. counter: Byte;
  303. begin
  304. GetProgramName:='';
  305. FillChar(s1,255,#0);
  306. if GetProgramName(@s1[1],255) then begin
  307. { now check out and assign the length of the string }
  308. counter := 1;
  309. while (s1[counter]<>#0) and (counter<>0) do Inc(counter);
  310. s1[0]:=Char(counter-1);
  311. { now remove any component path which should not be there }
  312. for counter:=length(s1) downto 1 do
  313. if (s1[counter] = '/') or (s1[counter] = ':') then break;
  314. { readjust counterv to point to character }
  315. if counter<>1 then Inc(counter);
  316. GetProgramName:=copy(s1,counter,length(s1));
  317. end;
  318. end;
  319. {*****************************************************************************
  320. ParamStr/Randomize
  321. *****************************************************************************}
  322. { number of args }
  323. function paramcount : longint;
  324. begin
  325. if MOS_ambMsg<>nil then
  326. paramcount:=0
  327. else
  328. paramcount:=argc-1;
  329. end;
  330. { argument number l }
  331. function paramstr(l : longint) : string;
  332. var
  333. s1: String;
  334. begin
  335. paramstr:='';
  336. if MOS_ambMsg<>nil then exit;
  337. if l=0 then begin
  338. s1:=GetProgDir;
  339. if s1[length(s1)]=':' then paramstr:=s1+GetProgramName
  340. else paramstr:=s1+'/'+GetProgramName;
  341. end else begin
  342. if (l>0) and (l+1<=argc) then paramstr:=strpas(argv[l]);
  343. end;
  344. end;
  345. { set randseed to a new pseudo random value }
  346. procedure randomize;
  347. var tmpTime: TDateStamp;
  348. begin
  349. DateStamp(@tmpTime);
  350. randseed:=tmpTime.ds_tick;
  351. end;
  352. {*****************************************************************************
  353. Heap Management
  354. *****************************************************************************}
  355. var
  356. int_heap : LongInt; external name 'HEAP';
  357. int_heapsize : LongInt; external name 'HEAPSIZE';
  358. { first address of heap }
  359. function getheapstart:pointer;
  360. begin
  361. getheapstart:=@int_heap;
  362. end;
  363. { current length of heap }
  364. function getheapsize:longint;
  365. begin
  366. getheapsize:=int_heapsize;
  367. end;
  368. { function to allocate size bytes more for the program }
  369. { must return the first address of new data space or nil if fail }
  370. function Sbrk(size : longint):pointer;
  371. begin
  372. Sbrk:=AllocPooled(MOS_heapPool,size);
  373. end;
  374. {*****************************************************************************
  375. OS Memory allocation / deallocation
  376. ****************************************************************************}
  377. function SysOSAlloc(size: ptrint): pointer;
  378. begin
  379. result := sbrk(size);
  380. end;
  381. {$define HAS_SYSOSFREE}
  382. procedure SysOSFree(p: pointer; size: ptrint);
  383. begin
  384. FreePooled(MOS_heapPool,p,size);
  385. end;
  386. {$I heap.inc}
  387. {*****************************************************************************
  388. Directory Handling
  389. *****************************************************************************}
  390. procedure mkdir(const s : string);[IOCheck];
  391. var
  392. buffer : array[0..255] of char;
  393. j : Integer;
  394. tmpStr : string;
  395. tmpLock : LongInt;
  396. begin
  397. checkCTRLC;
  398. if (s='') or (InOutRes<>0) then exit;
  399. tmpStr:=s;
  400. for j:=1 to length(tmpStr) do
  401. if tmpStr[j]='\' then tmpStr[j]:='/';
  402. move(tmpStr[1],buffer,length(tmpStr));
  403. buffer[length(tmpStr)]:=#0;
  404. tmpLock:=CreateDir(buffer);
  405. if tmpLock=0 then begin
  406. dosError2InOut(IoErr);
  407. exit;
  408. end;
  409. UnLock(tmpLock);
  410. end;
  411. procedure rmdir(const s : string);[IOCheck];
  412. var
  413. buffer : array[0..255] of char;
  414. j : Integer;
  415. tmpStr : string;
  416. begin
  417. checkCTRLC;
  418. if (s='.') then InOutRes:=16;
  419. If (s='') or (InOutRes<>0) then exit;
  420. tmpStr:=s;
  421. for j:=1 to length(tmpStr) do
  422. if tmpStr[j] = '\' then tmpStr[j] := '/';
  423. move(tmpStr[1],buffer,length(tmpStr));
  424. buffer[length(tmpStr)]:=#0;
  425. if not DeleteFile(buffer) then
  426. dosError2InOut(IoErr);
  427. end;
  428. procedure chdir(const s : string);[IOCheck];
  429. var
  430. buffer : array[0..255] of char;
  431. alock : LongInt;
  432. FIB : PFileInfoBlock;
  433. j : Integer;
  434. tmpStr : string;
  435. begin
  436. checkCTRLC;
  437. If (s='') or (InOutRes<>0) then exit;
  438. tmpStr:=s;
  439. for j:=1 to length(tmpStr) do
  440. if tmpStr[j]='\' then tmpStr[j]:='/';
  441. { Return parent directory }
  442. if s='..' then begin
  443. getdir(0,tmpStr);
  444. j:=length(tmpStr);
  445. { Look through the previous paths }
  446. while (tmpStr[j]<>'/') and (tmpStr[j]<>':') and (j>0) do
  447. dec(j);
  448. if j>0 then
  449. tmpStr:=copy(tmpStr,1,j);
  450. end;
  451. alock:=0;
  452. move(tmpStr[1],buffer,length(tmpStr));
  453. buffer[length(tmpStr)]:=#0;
  454. { Changing the directory is a pretty complicated affair }
  455. { 1) Obtain a lock on the directory }
  456. { 2) CurrentDir the lock }
  457. alock:=Lock(buffer,SHARED_LOCK);
  458. if alock=0 then begin
  459. dosError2InOut(IoErr);
  460. exit;
  461. end;
  462. FIB:=nil;
  463. new(FIB);
  464. if (Examine(alock,FIB)=True) and (FIB^.fib_DirEntryType>0) then begin
  465. alock := CurrentDir(alock);
  466. if MOS_OrigDir=0 then begin
  467. MOS_OrigDir:=alock;
  468. alock:=0;
  469. end;
  470. end;
  471. if alock<>0 then Unlock(alock);
  472. if assigned(FIB) then dispose(FIB)
  473. end;
  474. procedure GetDir (DriveNr: byte; var Dir: ShortString);
  475. var tmpbuf: array[0..255] of char;
  476. begin
  477. checkCTRLC;
  478. Dir:='';
  479. if not GetCurrentDirName(tmpbuf,256) then
  480. dosError2InOut(IoErr)
  481. else
  482. Dir:=strpas(tmpbuf);
  483. end;
  484. {****************************************************************************
  485. Low level File Routines
  486. All these functions can set InOutRes on errors
  487. ****************************************************************************}
  488. { close a file from the handle value }
  489. procedure do_close(handle : longint);
  490. begin
  491. RemoveFromList(MOS_fileList,handle);
  492. { Do _NOT_ check CTRL_C on Close, because it will conflict
  493. with System_Exit! }
  494. if not dosClose(handle) then
  495. dosError2InOut(IoErr);
  496. end;
  497. procedure do_erase(p : pchar);
  498. begin
  499. checkCTRLC;
  500. if not DeleteFile(p) then
  501. dosError2InOut(IoErr);
  502. end;
  503. procedure do_rename(p1,p2 : pchar);
  504. begin
  505. checkCTRLC;
  506. if not dosRename(p1,p2) then
  507. dosError2InOut(IoErr);
  508. end;
  509. function do_write(h:longint; addr: pointer; len: longint) : longint;
  510. var dosResult: LongInt;
  511. begin
  512. checkCTRLC;
  513. do_write:=0;
  514. if len<=0 then exit;
  515. dosResult:=dosWrite(h,addr,len);
  516. if dosResult<0 then begin
  517. dosError2InOut(IoErr);
  518. end else begin
  519. do_write:=dosResult;
  520. end;
  521. end;
  522. function do_read(h:longint; addr: pointer; len: longint) : longint;
  523. var dosResult: LongInt;
  524. begin
  525. checkCTRLC;
  526. do_read:=0;
  527. if len<=0 then exit;
  528. dosResult:=dosRead(h,addr,len);
  529. if dosResult<0 then begin
  530. dosError2InOut(IoErr);
  531. end else begin
  532. do_read:=dosResult;
  533. end
  534. end;
  535. function do_filepos(handle : longint) : longint;
  536. var dosResult: LongInt;
  537. begin
  538. checkCTRLC;
  539. do_filepos:=0;
  540. { Seeking zero from OFFSET_CURRENT to find out where we are }
  541. dosResult:=dosSeek(handle,0,OFFSET_CURRENT);
  542. if dosResult<0 then begin
  543. dosError2InOut(IoErr);
  544. end else begin
  545. do_filepos:=dosResult;
  546. end;
  547. end;
  548. procedure do_seek(handle,pos : longint);
  549. begin
  550. checkCTRLC;
  551. { Seeking from OFFSET_BEGINNING }
  552. if dosSeek(handle,pos,OFFSET_BEGINNING)<0 then
  553. dosError2InOut(IoErr);
  554. end;
  555. function do_seekend(handle:longint):longint;
  556. var dosResult: LongInt;
  557. begin
  558. checkCTRLC;
  559. do_seekend:=0;
  560. { Seeking to OFFSET_END }
  561. dosResult:=dosSeek(handle,0,OFFSET_END);
  562. if dosResult<0 then begin
  563. dosError2InOut(IoErr);
  564. end else begin
  565. do_seekend:=dosResult;
  566. end
  567. end;
  568. function do_filesize(handle : longint) : longint;
  569. var currfilepos: longint;
  570. begin
  571. checkCTRLC;
  572. currfilepos:=do_filepos(handle);
  573. { We have to do this twice, because seek returns the OLD position }
  574. do_filesize:=do_seekend(handle);
  575. do_filesize:=do_seekend(handle);
  576. do_seek(handle,currfilepos)
  577. end;
  578. { truncate at a given position }
  579. procedure do_truncate (handle,pos:longint);
  580. begin
  581. checkCTRLC;
  582. { Seeking from OFFSET_BEGINNING }
  583. if SetFileSize(handle,pos,OFFSET_BEGINNING)<0 then
  584. dosError2InOut(IoErr);
  585. end;
  586. procedure do_open(var f;p:pchar;flags:longint);
  587. {
  588. filerec and textrec have both handle and mode as the first items so
  589. they could use the same routine for opening/creating.
  590. when (flags and $10) the file will be append
  591. when (flags and $100) the file will be truncate/rewritten
  592. when (flags and $1000) there is no check for close (needed for textfiles)
  593. }
  594. var
  595. i,j : LongInt;
  596. openflags : LongInt;
  597. path : String;
  598. buffer : array[0..255] of Char;
  599. index : Integer;
  600. s : String;
  601. begin
  602. path:=strpas(p);
  603. for index:=1 to length(path) do
  604. if path[index]='\' then path[index]:='/';
  605. { remove any dot characters and replace by their current }
  606. { directory equivalent. }
  607. { look for parent directory }
  608. if pos('../',path) = 1 then
  609. begin
  610. delete(path,1,3);
  611. getdir(0,s);
  612. j:=length(s);
  613. while (s[j]<>'/') and (s[j]<>':') and (j>0) do
  614. dec(j);
  615. if j > 0 then
  616. s:=copy(s,1,j);
  617. path:=s+path;
  618. end
  619. else
  620. { look for current directory }
  621. if pos('./',path) = 1 then
  622. begin
  623. delete(path,1,2);
  624. getdir(0,s);
  625. if (s[length(s)]<>'/') and (s[length(s)]<>':') then
  626. s:=s+'/';
  627. path:=s+path;
  628. end;
  629. move(path[1],buffer,length(path));
  630. buffer[length(path)]:=#0;
  631. { close first if opened }
  632. if ((flags and $10000)=0) then
  633. begin
  634. case filerec(f).mode of
  635. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  636. fmclosed : ;
  637. else begin
  638. inoutres:=102; {not assigned}
  639. exit;
  640. end;
  641. end;
  642. end;
  643. { reset file handle }
  644. filerec(f).handle:=UnusedHandle;
  645. { convert filemode to filerec modes }
  646. { READ/WRITE on existing file }
  647. { RESET/APPEND }
  648. openflags := 1005;
  649. case (flags and 3) of
  650. 0 : filerec(f).mode:=fminput;
  651. 1 : filerec(f).mode:=fmoutput;
  652. 2 : filerec(f).mode:=fminout;
  653. end;
  654. { rewrite (create a new file) }
  655. if (flags and $1000)<>0 then openflags := 1006;
  656. { empty name is special }
  657. if p[0]=#0 then
  658. begin
  659. case filerec(f).mode of
  660. fminput :
  661. filerec(f).handle:=StdInputHandle;
  662. fmappend,
  663. fmoutput : begin
  664. filerec(f).handle:=StdOutputHandle;
  665. filerec(f).mode:=fmoutput; {fool fmappend}
  666. end;
  667. end;
  668. exit;
  669. end;
  670. i:=Open(buffer,openflags);
  671. if i=0 then
  672. begin
  673. dosError2InOut(IoErr);
  674. end else begin
  675. AddToList(MOS_fileList,i);
  676. filerec(f).handle:=i;
  677. end;
  678. { append mode }
  679. if ((Flags and $100)<>0) and (FileRec(F).Handle<>UnusedHandle) then
  680. begin
  681. do_seekend(filerec(f).handle);
  682. filerec(f).mode:=fmoutput; {fool fmappend}
  683. end;
  684. end;
  685. function do_isdevice(handle:longint):boolean;
  686. begin
  687. if (handle=StdOutputHandle) or (handle=StdInputHandle) or
  688. (handle=StdErrorHandle) then
  689. do_isdevice:=True
  690. else
  691. do_isdevice:=False;
  692. end;
  693. {*****************************************************************************
  694. UnTyped File Handling
  695. *****************************************************************************}
  696. {$i file.inc}
  697. {*****************************************************************************
  698. Typed File Handling
  699. *****************************************************************************}
  700. {$i typefile.inc}
  701. {*****************************************************************************
  702. Text File Handling
  703. *****************************************************************************}
  704. {$I text.inc}
  705. { MorphOS specific startup }
  706. procedure SysInitMorphOS;
  707. var self: PProcess;
  708. begin
  709. self:=PProcess(FindTask(nil));
  710. if self^.pr_CLI=0 then begin
  711. { if we're running from Ambient/Workbench, we catch its message }
  712. WaitPort(@self^.pr_MsgPort);
  713. MOS_ambMsg:=GetMsg(@self^.pr_MsgPort);
  714. end;
  715. MOS_DOSBase:=OpenLibrary('dos.library',50);
  716. if MOS_DOSBase=nil then Halt(1);
  717. MOS_UtilityBase:=OpenLibrary('utility.library',50);
  718. if MOS_UtilityBase=nil then Halt(1);
  719. { Creating the memory pool for growing heap }
  720. MOS_heapPool:=CreatePool(MEMF_FAST,growheapsize2,growheapsize1);
  721. if MOS_heapPool=nil then Halt(1);
  722. if MOS_ambMsg=nil then begin
  723. StdInputHandle:=dosInput;
  724. StdOutputHandle:=dosOutput;
  725. end else begin
  726. MOS_ConHandle:=Open(MOS_ConName,1005);
  727. if MOS_ConHandle<>0 then begin
  728. StdInputHandle:=MOS_ConHandle;
  729. StdOutputHandle:=MOS_ConHandle;
  730. end else
  731. Halt(1);
  732. end;
  733. end;
  734. procedure SysInitStdIO;
  735. begin
  736. OpenStdIO(Input,fmInput,StdInputHandle);
  737. OpenStdIO(Output,fmOutput,StdOutputHandle);
  738. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  739. { * MorphOS doesn't have a separate stderr, just like AmigaOS (???) * }
  740. StdErrorHandle:=StdOutputHandle;
  741. // OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  742. end;
  743. begin
  744. IsConsole := TRUE;
  745. IsLibrary := FALSE;
  746. StackLength := InitialStkLen;
  747. StackBottom := Sptr - StackLength;
  748. { OS specific startup }
  749. MOS_ambMsg:=nil;
  750. MOS_origDir:=0;
  751. MOS_fileList:=nil;
  752. envp:=nil;
  753. SysInitMorphOS;
  754. { Set up signals handlers }
  755. // InstallSignals;
  756. { Setup heap }
  757. InitHeap;
  758. SysInitExceptions;
  759. { Setup stdin, stdout and stderr }
  760. SysInitStdIO;
  761. { Reset IO Error }
  762. InOutRes:=0;
  763. { Arguments }
  764. GenerateArgs;
  765. (* This should be changed to a real value during *)
  766. (* thread driver initialization if appropriate. *)
  767. ThreadID := 1;
  768. {$ifdef HASVARIANT}
  769. initvariantmanager;
  770. {$endif HASVARIANT}
  771. end.
  772. {
  773. $Log$
  774. Revision 1.18 2004-08-09 00:12:40 karoly
  775. * changes to work with updated doslib includes
  776. Revision 1.17 2004/08/03 15:59:41 karoly
  777. * more cleanup & more includes
  778. Revision 1.16 2004/06/26 20:48:24 karoly
  779. * more cleanup + changes to use new includes
  780. Revision 1.15 2004/06/23 13:27:32 karoly
  781. * fixed system unit for the new heap manager
  782. Revision 1.14 2004/06/17 16:16:14 peter
  783. * New heapmanager that releases memory back to the OS, donated
  784. by Micha Nelissen
  785. Revision 1.13 2004/06/13 22:50:47 karoly
  786. * cleanup and changes to use new includes
  787. Revision 1.12 2004/06/06 23:31:13 karoly
  788. * fixed dos_UnLockDosList from being nonsense, and some cleanup
  789. Revision 1.11 2004/06/06 19:18:05 karoly
  790. + added support for paramstr(0)
  791. Revision 1.10 2004/06/05 19:49:19 karoly
  792. + added console I/O support when running from Ambient
  793. Revision 1.9 2004/05/12 23:18:54 karoly
  794. * fixed do_read and dos_Read from being nonsense
  795. Revision 1.8 2004/05/12 20:26:04 karoly
  796. + added syscalls and structures necessary for DOS unit
  797. Revision 1.7 2004/05/12 15:34:16 karoly
  798. * fixed startup code from endless wait when not started from Ambient
  799. Revision 1.6 2004/05/09 14:42:59 karoly
  800. * again, few more new things added
  801. Revision 1.5 2004/05/09 02:02:42 karoly
  802. * more things got implemented
  803. Revision 1.4 2004/05/02 02:06:57 karoly
  804. + most of file I/O calls implemented
  805. Revision 1.3 2004/05/01 15:09:47 karoly
  806. * first working system unit (very limited yet)
  807. Revision 1.2  2004/04/08 06:28:29  karoly
  808. * first steps to have a morphos system unit
  809. Revision 1.1 2004/02/13 07:19:53 karoly
  810. * quick hack from Linux system unit
  811. }