system.pp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226
  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. {*****************************************************************************
  39. MorphOS structures
  40. *****************************************************************************}
  41. {$include execd.inc}
  42. type
  43. PClockData = ^TClockData;
  44. TClockData = packed Record
  45. sec : Word;
  46. min : Word;
  47. hour : Word;
  48. mday : Word;
  49. month: Word;
  50. year : Word;
  51. wday : Word;
  52. end;
  53. TDateStamp = packed record
  54. ds_Days : LongInt; { Number of days since Jan. 1, 1978 }
  55. ds_Minute : LongInt; { Number of minutes past midnight }
  56. ds_Tick : LongInt; { Number of ticks past minute }
  57. end;
  58. PDateStamp = ^TDateStamp;
  59. PFileInfoBlock = ^TFileInfoBlock;
  60. TFileInfoBlock = packed record
  61. fib_DiskKey : LongInt;
  62. fib_DirEntryType : LongInt;
  63. { Type of Directory. If < 0, then a plain file. If > 0 a directory }
  64. fib_FileName : Array [0..107] of Char;
  65. { Null terminated. Max 30 chars used for now }
  66. fib_Protection : LongInt;
  67. { bit mask of protection, rwxd are 3-0. }
  68. fib_EntryType : LongInt;
  69. fib_Size : LongInt; { Number of bytes in file }
  70. fib_NumBlocks : LongInt; { Number of blocks in file }
  71. fib_Date : TDateStamp; { Date file last changed }
  72. fib_Comment : Array [0..79] of Char;
  73. { Null terminated comment associated with file }
  74. fib_Reserved : Array [0..35] of Char;
  75. end;
  76. PProcess = ^TProcess;
  77. TProcess = packed record
  78. pr_Task : TTask;
  79. pr_MsgPort : TMsgPort; { This is BPTR address from DOS functions }
  80. pr_Pad : Word; { Remaining variables on 4 byte boundaries }
  81. pr_SegList : Pointer; { Array of seg lists used by this process }
  82. pr_StackSize : Longint; { Size of process stack in bytes }
  83. pr_GlobVec : Pointer; { Global vector for this process (BCPL) }
  84. pr_TaskNum : Longint; { CLI task number of zero if not a CLI }
  85. pr_StackBase : DWord; { Ptr to high memory end of process stack }
  86. pr_Result2 : Longint; { Value of secondary result from last call }
  87. pr_CurrentDir : DWord; { Lock associated with current directory }
  88. pr_CIS : DWord; { Current CLI Input Stream }
  89. pr_COS : DWord; { Current CLI Output Stream }
  90. pr_ConsoleTask : Pointer; { Console handler process for current window }
  91. pr_FileSystemTask: Pointer; { File handler process for current drive }
  92. pr_CLI : DWord; { pointer to ConsoleLineInterpreter }
  93. pr_ReturnAddr : Pointer; { pointer to previous stack frame }
  94. pr_PktWait : Pointer; { Function to be called when awaiting msg }
  95. pr_WindowPtr : Pointer; { Window for error printing }
  96. { following definitions are new with 2.0 }
  97. pr_HomeDir : DWord; { Home directory of executing program }
  98. pr_Flags : Longint; { flags telling dos about process }
  99. pr_ExitCode : Pointer; { code to call on exit of program OR NULL }
  100. pr_ExitData : Longint; { Passed as an argument to pr_ExitCode. }
  101. pr_Arguments : PChar; { Arguments passed to the process at start }
  102. pr_LocalVars : TMinList; { Local environment variables }
  103. pr_ShellPrivate : Longint; { for the use of the current shell }
  104. pr_CES : DWord; { Error stream - IF NULL, use pr_COS }
  105. end;
  106. PInfoData = ^TInfoData;
  107. TInfoData = packed record
  108. id_NumSoftErrors: LongInt; { number of soft errors on disk }
  109. id_UnitNumber : LongInt; { Which unit disk is (was) mounted on }
  110. id_DiskState : LongInt; { See defines below }
  111. id_NumBlocks : LongInt; { Number of blocks on disk }
  112. id_NumBlocksUsed: LongInt; { Number of block in use }
  113. id_BytesPerBlock: LongInt;
  114. id_DiskType : LongInt; { Disk Type code }
  115. id_VolumeNode : LongInt; { BCPL pointer to volume node }
  116. id_InUse : LongInt; { Flag, zero if not in use }
  117. end;
  118. PChain = ^TChain;
  119. TChain = packed record
  120. an_Child : PChain;
  121. an_Parent: PChain;
  122. an_Lock : LongInt;
  123. an_info : TFileInfoBlock;
  124. an_Flags : ShortInt;
  125. an_string: Array[0..0] of char;
  126. end;
  127. PAnchorPath = ^TAnchorPath;
  128. TAnchorPath = packed record
  129. ap_Base : PChain; { pointer to first anchor }
  130. ap_First : PChain; { pointer to last anchor }
  131. ap_BreakBits: LongInt; { Bits we want to break on }
  132. ap_FondBreak: LongInt; { Bits we broke on. Also returns ERROR_BREAK }
  133. ap_Flags : ShortInt; { New use for extra word. }
  134. ap_reserved : Byte;
  135. ap_StrLen : Word;
  136. ap_Info : TFileInfoBlock;
  137. ap_Buf : array[0..0] of Char; { Buffer for path name, allocated by user }
  138. end;
  139. PDOSList = ^TDOSList;
  140. TDOSList = packed record
  141. dol_Next: LongInt; { bptr to next device on list }
  142. dol_Type: LongInt; { see DLT below }
  143. dol_Task: Pointer; { ptr to handler task }
  144. dol_Lock: LongInt;
  145. dol_Misc: array[0..23] of ShortInt;
  146. dol_Name: LongInt; { bptr to bcpl name }
  147. end;
  148. var
  149. MOS_ExecBase : Pointer; external name '_ExecBase';
  150. MOS_DOSBase : Pointer;
  151. MOS_UtilityBase: Pointer;
  152. MOS_heapPool : Pointer; { pointer for the OS pool for growing the heap }
  153. MOS_origDir : LongInt; { original directory on startup }
  154. MOS_ambMsg : PMessage;
  155. MOS_ConName : PChar ='CON:10/30/620/100/FPC Console Output/AUTO/CLOSE/WAIT';
  156. MOS_ConHandle: LongInt;
  157. argc: LongInt;
  158. argv: PPChar;
  159. envp: PPChar;
  160. {*****************************************************************************
  161. MorphOS functions
  162. *****************************************************************************}
  163. { dos.library functions }
  164. function dos_Output: LongInt; SysCall MOS_DOSBase 60;
  165. function dos_Input: LongInt; SysCall MOS_DOSBase 54;
  166. function dos_IoErr: LongInt; SysCall MOS_DOSBase 132;
  167. function dos_GetArgStr: PChar; SysCall MOS_DOSBase 534;
  168. function dos_Open(fname: PChar location 'd1';
  169. accessMode: LongInt location 'd2'): LongInt; SysCall MOS_DOSBase 30;
  170. function dos_Close(fileh: LongInt location 'd1'): Boolean; SysCall MOS_DOSBase 36;
  171. function dos_Seek(fileh: LongInt location 'd1';
  172. position: LongInt location 'd2';
  173. posmode: LongInt location 'd3'): LongInt; SysCall MOS_DOSBase 66;
  174. function dos_SetFileSize(fileh: LongInt location 'd1';
  175. position: LongInt location 'd2';
  176. posmode: LongInt location 'd3'): LongInt; SysCall MOS_DOSBase 456;
  177. function dos_Read(fileh: LongInt location 'd1';
  178. buffer: Pointer location 'd2';
  179. length: LongInt location 'd3'): LongInt; SysCall MOS_DOSBase 42;
  180. function dos_Write(fileh: LongInt location 'd1';
  181. buffer: Pointer location 'd2';
  182. length: LongInt location 'd3'): LongInt; SysCall MOS_DOSBase 48;
  183. function dos_WriteChars(buf: PChar location 'd1';
  184. buflen: LongInt location 'd2'): LongInt; SysCall MOS_DOSBase 942;
  185. function dos_Rename(oldName: PChar location 'd1';
  186. newName: PChar location 'd2'): Boolean; SysCall MOS_DOSBase 78;
  187. function dos_DeleteFile(fname: PChar location 'd1'): Boolean; SysCall MOS_DOSBase 72;
  188. function dos_GetCurrentDirName(buf: PChar location 'd1';
  189. len: LongInt location 'd2'): Boolean; SysCall MOS_DOSBase 564;
  190. function dos_Lock(lname: PChar location 'd1';
  191. accessMode: LongInt location 'd2'): LongInt; SysCall MOS_DOSBase 84;
  192. procedure dos_Unlock(lock: LongInt location 'd1'); SysCall MOS_DOSBase 90;
  193. function dos_CurrentDir(lock: LongInt location 'd1'): LongInt; SysCall MOS_DOSBase 126;
  194. function dos_Examine(lock: LongInt location 'd1';
  195. FileInfoBlock: Pointer location 'd2'): Boolean; SysCall MOS_DOSBase 102;
  196. function dos_NameFromLock(lock: LongInt location 'd1';
  197. buffer: PChar location 'd2';
  198. len: LongInt location 'd3'): Boolean; SysCall MOS_DOSBase 402;
  199. function dos_Info(lock: LongInt location 'd1';
  200. parameterBlock: PInfoData location 'd2'): Boolean; SysCall MOS_DOSBase 114;
  201. function dos_CreateDir(dname: PChar location 'd1'): LongInt; SysCall MOS_DOSBase 120;
  202. function dos_DateStamp(var ds: TDateStamp location 'd1'): LongInt; SysCall MOS_DOSBase 192;
  203. function dos_SystemTagList(command: PChar location 'd1';
  204. tags: Pointer location 'd2'): LongInt; SysCall MOS_DOSBase 606;
  205. function dos_GetVar(vname: PChar location 'd1';
  206. buffer: PChar location 'd2';
  207. size: LongInt location 'd3';
  208. flags: LongInt location 'd4'): LongInt; SysCall MOS_DOSBase 906;
  209. function dos_MatchFirst(pat: PChar location 'd1';
  210. anchor: PAnchorPath location 'd2'): LongInt; SysCall MOS_DOSBase 822;
  211. function dos_MatchNext(anchor: PAnchorPath location 'd1'): LongInt; SysCall MOS_DOSBase 828;
  212. procedure dos_MatchEnd(anchor: PAnchorPath location 'd1') SysCall MOS_DOSBase 834;
  213. function dos_LockDosList(flags: LongInt location 'd1'): PDOSList; SysCall MOS_DOSBase 654;
  214. procedure dos_UnLockDosList(flags: LongInt location 'd1'); SysCall MOS_DOSBase 660;
  215. function dos_NextDosEntry(dlist: PDOSList location 'd1';
  216. flags: LongInt location 'd2'): PDOSList; SysCall MOS_DOSBase 690;
  217. function dos_SetProtection(name: PChar location 'd1';
  218. mask: LongInt location 'd2'): Boolean; SysCall MOS_DOSBase 186;
  219. function dos_SetFileDate(name: PChar location 'd1';
  220. date: PDateStamp location 'd2'): Boolean; SysCall MOS_DOSBase 396;
  221. function dos_GetProgramDir: LongInt; SysCall MOS_DOSBase 600;
  222. function dos_GetProgramName(buf: PChar location 'd1';
  223. len: LongInt location 'd2'): Boolean; SysCall MOS_DOSBase 576;
  224. { utility.library functions }
  225. function util_Date2Amiga(date: PClockData location 'a0'): LongInt; SysCall MOS_UtilityBase 126;
  226. procedure util_Amiga2Date(amigatime: LongInt location 'd0';
  227. resultat: PClockData location 'a0'); SysCall MOS_UtilityBase 120;
  228. implementation
  229. {$I system.inc}
  230. {*****************************************************************************
  231. MorphOS functions
  232. *****************************************************************************}
  233. { exec.library functions }
  234. {$include execf.inc}
  235. {*****************************************************************************
  236. System Dependent Structures/Consts
  237. *****************************************************************************}
  238. { Errors from dos_IoErr(), etc. }
  239. const
  240. ERROR_NO_FREE_STORE = 103;
  241. ERROR_TASK_TABLE_FULL = 105;
  242. ERROR_BAD_TEMPLATE = 114;
  243. ERROR_BAD_NUMBER = 115;
  244. ERROR_REQUIRED_ARG_MISSING = 116;
  245. ERROR_KEY_NEEDS_ARG = 117;
  246. ERROR_TOO_MANY_ARGS = 118;
  247. ERROR_UNMATCHED_QUOTES = 119;
  248. ERROR_LINE_TOO_LONG = 120;
  249. ERROR_FILE_NOT_OBJECT = 121;
  250. ERROR_INVALID_RESIDENT_LIBRARY = 122;
  251. ERROR_NO_DEFAULT_DIR = 201;
  252. ERROR_OBJECT_IN_USE = 202;
  253. ERROR_OBJECT_EXISTS = 203;
  254. ERROR_DIR_NOT_FOUND = 204;
  255. ERROR_OBJECT_NOT_FOUND = 205;
  256. ERROR_BAD_STREAM_NAME = 206;
  257. ERROR_OBJECT_TOO_LARGE = 207;
  258. ERROR_ACTION_NOT_KNOWN = 209;
  259. ERROR_INVALID_COMPONENT_NAME = 210;
  260. ERROR_INVALID_LOCK = 211;
  261. ERROR_OBJECT_WRONG_TYPE = 212;
  262. ERROR_DISK_NOT_VALIDATED = 213;
  263. ERROR_DISK_WRITE_PROTECTED = 214;
  264. ERROR_RENAME_ACROSS_DEVICES = 215;
  265. ERROR_DIRECTORY_NOT_EMPTY = 216;
  266. ERROR_TOO_MANY_LEVELS = 217;
  267. ERROR_DEVICE_NOT_MOUNTED = 218;
  268. ERROR_SEEK_ERROR = 219;
  269. ERROR_COMMENT_TOO_BIG = 220;
  270. ERROR_DISK_FULL = 221;
  271. ERROR_DELETE_PROTECTED = 222;
  272. ERROR_WRITE_PROTECTED = 223;
  273. ERROR_READ_PROTECTED = 224;
  274. ERROR_NOT_A_DOS_DISK = 225;
  275. ERROR_NO_DISK = 226;
  276. ERROR_NO_MORE_ENTRIES = 232;
  277. { added for AOS 1.4 }
  278. ERROR_IS_SOFT_LINK = 233;
  279. ERROR_OBJECT_LINKED = 234;
  280. ERROR_BAD_HUNK = 235;
  281. ERROR_NOT_IMPLEMENTED = 236;
  282. ERROR_RECORD_NOT_LOCKED = 240;
  283. ERROR_LOCK_COLLISION = 241;
  284. ERROR_LOCK_TIMEOUT = 242;
  285. ERROR_UNLOCK_ERROR = 243;
  286. { DOS file offset modes }
  287. const
  288. OFFSET_BEGINNING = -1;
  289. OFFSET_CURRENT = 0;
  290. OFFSET_END = 1;
  291. { Lock AccessMode }
  292. const
  293. SHARED_LOCK = -2;
  294. ACCESS_READ = SHARED_LOCK;
  295. EXCLUSIVE_LOCK = -1;
  296. ACCESS_WRITE = EXCLUSIVE_LOCK;
  297. const
  298. CTRL_C = 20; { Error code on CTRL-C press }
  299. SIGBREAKF_CTRL_C = $1000; { CTRL-C signal flags }
  300. {*****************************************************************************
  301. MorphOS File-handling Support Functions
  302. *****************************************************************************}
  303. type
  304. { AmigaOS does not automatically close opened files on exit back to }
  305. { the operating system, therefore as a precuation we close all files }
  306. { manually on exit. }
  307. PFileList = ^TFileList;
  308. TFileList = record { no packed, must be correctly aligned }
  309. handle : LongInt; { Handle to file }
  310. next : PFileList; { Next file in list }
  311. end;
  312. var
  313. MOS_fileList: PFileList; { List pointer to opened files }
  314. { Function to be called at program shutdown, to close all opened files }
  315. procedure CloseList(l: PFileList);
  316. var
  317. tmpNext : PFileList;
  318. tmpHandle : LongInt;
  319. begin
  320. if l=nil then exit;
  321. { First, close all tracked files }
  322. tmpNext:=l^.next;
  323. while tmpNext<>nil do begin
  324. tmpHandle:=tmpNext^.handle;
  325. if (tmpHandle<>StdInputHandle) and (tmpHandle<>StdOutputHandle)
  326. and (tmpHandle<>StdErrorHandle) then begin
  327. dos_Close(tmpHandle);
  328. end;
  329. tmpNext:=tmpNext^.next;
  330. end;
  331. { Next, erase the linked list }
  332. while l<>nil do begin
  333. tmpNext:=l;
  334. l:=l^.next;
  335. dispose(tmpNext);
  336. end;
  337. end;
  338. { Function to be called to add a file to the opened file list }
  339. procedure AddToList(var l: PFileList; h: LongInt);
  340. var
  341. p : PFileList;
  342. inList: Boolean;
  343. begin
  344. inList:=False;
  345. if l<>nil then begin
  346. { if there is a valid filelist, search for the value }
  347. { in the list to avoid double additions }
  348. p:=l;
  349. while (p^.next<>nil) and (not inList) do
  350. if p^.next^.handle=h then inList:=True
  351. else p:=p^.next;
  352. p:=nil;
  353. end else begin
  354. { if the list is not yet allocated, allocate it. }
  355. New(l);
  356. l^.next:=nil;
  357. end;
  358. if not inList then begin
  359. New(p);
  360. p^.handle:=h;
  361. p^.next:=l^.next;
  362. l^.next:=p;
  363. end;
  364. end;
  365. { Function to be called to remove a file from the list }
  366. procedure RemoveFromList(var l: PFileList; h: longint);
  367. var
  368. p : PFileList;
  369. inList: Boolean;
  370. begin
  371. if l=nil then exit;
  372. inList:=False;
  373. p:=l;
  374. while (p^.next<>nil) and (not inList) do
  375. if p^.next^.handle=h then inList:=True
  376. else p:=p^.next;
  377. if p^.next<>nil then begin
  378. dispose(p^.next);
  379. p^.next:=p^.next^.next;
  380. end;
  381. end;
  382. {*****************************************************************************
  383. Misc. System Dependent Functions
  384. *****************************************************************************}
  385. procedure haltproc(e:longint);cdecl;external name '_haltproc';
  386. procedure System_exit;
  387. begin
  388. { We must remove the CTRL-C FALG here because halt }
  389. { may call I/O routines, which in turn might call }
  390. { halt, so a recursive stack crash }
  391. if BreakOn then begin
  392. if (SetSignal(0,0) and SIGBREAKF_CTRL_C)<>0 then
  393. SetSignal(0,SIGBREAKF_CTRL_C);
  394. end;
  395. { Closing opened files }
  396. CloseList(MOS_fileList);
  397. if MOS_UtilityBase<>nil then CloseLibrary(MOS_UtilityBase);
  398. if MOS_DOSBase<>nil then CloseLibrary(MOS_DOSBase);
  399. if MOS_heapPool<>nil then DeletePool(MOS_heapPool);
  400. haltproc(ExitCode);
  401. end;
  402. { Converts a MorphOS dos.library error code to a TP compatible error code }
  403. { Based on 1.0.x Amiga RTL }
  404. procedure dosError2InOut(errno: LongInt);
  405. begin
  406. case errno of
  407. ERROR_BAD_NUMBER,
  408. ERROR_ACTION_NOT_KNOWN,
  409. ERROR_NOT_IMPLEMENTED : InOutRes := 1;
  410. ERROR_OBJECT_NOT_FOUND : InOutRes := 2;
  411. ERROR_DIR_NOT_FOUND : InOutRes := 3;
  412. ERROR_DISK_WRITE_PROTECTED : InOutRes := 150;
  413. ERROR_OBJECT_WRONG_TYPE : InOutRes := 151;
  414. ERROR_OBJECT_EXISTS,
  415. ERROR_DELETE_PROTECTED,
  416. ERROR_WRITE_PROTECTED,
  417. ERROR_READ_PROTECTED,
  418. ERROR_OBJECT_IN_USE,
  419. ERROR_DIRECTORY_NOT_EMPTY : InOutRes := 5;
  420. ERROR_NO_MORE_ENTRIES : InOutRes := 18;
  421. ERROR_RENAME_ACROSS_DEVICES : InOutRes := 17;
  422. ERROR_DISK_FULL : InOutRes := 101;
  423. ERROR_INVALID_RESIDENT_LIBRARY : InoutRes := 153;
  424. ERROR_BAD_HUNK : InOutRes := 153;
  425. ERROR_NOT_A_DOS_DISK : InOutRes := 157;
  426. ERROR_NO_DISK,
  427. ERROR_DISK_NOT_VALIDATED,
  428. ERROR_DEVICE_NOT_MOUNTED : InOutRes := 152;
  429. ERROR_SEEK_ERROR : InOutRes := 156;
  430. ERROR_LOCK_COLLISION,
  431. ERROR_LOCK_TIMEOUT,
  432. ERROR_UNLOCK_ERROR,
  433. ERROR_INVALID_LOCK,
  434. ERROR_INVALID_COMPONENT_NAME,
  435. ERROR_BAD_STREAM_NAME,
  436. ERROR_FILE_NOT_OBJECT : InOutRes := 6;
  437. else
  438. InOutres := errno;
  439. end;
  440. end;
  441. { Used for CTRL_C checking in I/O calls }
  442. procedure checkCTRLC;
  443. begin
  444. if BreakOn then begin
  445. if (SetSignal(0,0) And SIGBREAKF_CTRL_C)<>0 then begin
  446. { Clear CTRL-C signal }
  447. SetSignal(0,SIGBREAKF_CTRL_C);
  448. Halt(CTRL_C);
  449. end;
  450. end;
  451. end;
  452. { Generates correct argument array on startup }
  453. procedure GenerateArgs;
  454. var
  455. argvlen : longint;
  456. procedure allocarg(idx,len:longint);
  457. var
  458. i,oldargvlen : longint;
  459. begin
  460. if idx>=argvlen then
  461. begin
  462. oldargvlen:=argvlen;
  463. argvlen:=(idx+8) and (not 7);
  464. sysreallocmem(argv,argvlen*sizeof(pointer));
  465. for i:=oldargvlen to argvlen-1 do
  466. argv[i]:=nil;
  467. end;
  468. { use realloc to reuse already existing memory }
  469. sysreallocmem(argv[idx],len+1);
  470. end;
  471. var
  472. count: word;
  473. start: word;
  474. localindex: word;
  475. p : pchar;
  476. temp : string;
  477. begin
  478. p:=dos_GetArgStr;
  479. argvlen:=0;
  480. { Set argv[0] }
  481. temp:=paramstr(0);
  482. allocarg(0,length(temp));
  483. move(temp[1],argv[0]^,length(temp));
  484. argv[0][length(temp)]:=#0;
  485. { check if we're started from Ambient }
  486. if MOS_ambMsg<>nil then
  487. begin
  488. argc:=0;
  489. exit;
  490. end;
  491. { Handle the other args }
  492. count:=0;
  493. { first index is one }
  494. localindex:=1;
  495. while (p[count]<>#0) do
  496. begin
  497. while (p[count]=' ') or (p[count]=#9) or (p[count]=LineEnding) do inc(count);
  498. start:=count;
  499. while (p[count]<>#0) and (p[count]<>' ') and (p[count]<>#9) and (p[count]<>LineEnding) do inc(count);
  500. if (count-start>0) then
  501. begin
  502. allocarg(localindex,count-start);
  503. move(p[start],argv[localindex]^,count-start);
  504. argv[localindex][count-start]:=#0;
  505. inc(localindex);
  506. end;
  507. end;
  508. argc:=localindex;
  509. end;
  510. function GetProgramDir: String;
  511. var
  512. s1 : String;
  513. alock : LongInt;
  514. counter: Byte;
  515. begin
  516. GetProgramDir:='';
  517. FillChar(s1,255,#0);
  518. { GetLock of program directory }
  519. alock:=dos_GetProgramDir;
  520. if alock<>0 then begin
  521. if dos_NameFromLock(alock,@s1[1],255) then begin
  522. counter:=1;
  523. while (s1[counter]<>#0) and (counter<>0) do Inc(counter);
  524. s1[0]:=Char(counter-1);
  525. GetProgramDir:=s1;
  526. end;
  527. end;
  528. end;
  529. function GetProgramName: String;
  530. { Returns ONLY the program name }
  531. var
  532. s1 : String;
  533. counter: Byte;
  534. begin
  535. GetProgramName:='';
  536. FillChar(s1,255,#0);
  537. if dos_GetProgramName(@s1[1],255) then begin
  538. { now check out and assign the length of the string }
  539. counter := 1;
  540. while (s1[counter]<>#0) and (counter<>0) do Inc(counter);
  541. s1[0]:=Char(counter-1);
  542. { now remove any component path which should not be there }
  543. for counter:=length(s1) downto 1 do
  544. if (s1[counter] = '/') or (s1[counter] = ':') then break;
  545. { readjust counterv to point to character }
  546. if counter<>1 then Inc(counter);
  547. GetProgramName:=copy(s1,counter,length(s1));
  548. end;
  549. end;
  550. {*****************************************************************************
  551. ParamStr/Randomize
  552. *****************************************************************************}
  553. { number of args }
  554. function paramcount : longint;
  555. begin
  556. if MOS_ambMsg<>nil then
  557. paramcount:=0
  558. else
  559. paramcount:=argc-1;
  560. end;
  561. { argument number l }
  562. function paramstr(l : longint) : string;
  563. var
  564. s1: String;
  565. begin
  566. paramstr:='';
  567. if MOS_ambMsg<>nil then exit;
  568. if l=0 then begin
  569. s1:=GetProgramDir;
  570. if s1[length(s1)]=':' then paramstr:=s1+GetProgramName
  571. else paramstr:=s1+'/'+GetProgramName;
  572. end else begin
  573. if (l>0) and (l+1<=argc) then paramstr:=strpas(argv[l]);
  574. end;
  575. end;
  576. { set randseed to a new pseudo random value }
  577. procedure randomize;
  578. var tmpTime: TDateStamp;
  579. begin
  580. dos_DateStamp(tmpTime);
  581. randseed:=tmpTime.ds_tick;
  582. end;
  583. {*****************************************************************************
  584. Heap Management
  585. *****************************************************************************}
  586. var
  587. int_heap : LongInt; external name 'HEAP';
  588. int_heapsize : LongInt; external name 'HEAPSIZE';
  589. { first address of heap }
  590. function getheapstart:pointer;
  591. begin
  592. getheapstart:=@int_heap;
  593. end;
  594. { current length of heap }
  595. function getheapsize:longint;
  596. begin
  597. getheapsize:=int_heapsize;
  598. end;
  599. { function to allocate size bytes more for the program }
  600. { must return the first address of new data space or nil if fail }
  601. function Sbrk(size : longint):pointer;
  602. begin
  603. Sbrk:=AllocPooled(MOS_heapPool,size);
  604. end;
  605. {*****************************************************************************
  606. OS Memory allocation / deallocation
  607. ****************************************************************************}
  608. function SysOSAlloc(size: ptrint): pointer;
  609. begin
  610. result := sbrk(size);
  611. end;
  612. {$define HAS_SYSOSFREE}
  613. procedure SysOSFree(p: pointer; size: ptrint);
  614. begin
  615. FreePooled(MOS_heapPool,p,size);
  616. end;
  617. {$I heap.inc}
  618. {*****************************************************************************
  619. Directory Handling
  620. *****************************************************************************}
  621. procedure mkdir(const s : string);[IOCheck];
  622. var
  623. buffer : array[0..255] of char;
  624. j : Integer;
  625. tmpStr : string;
  626. tmpLock : LongInt;
  627. begin
  628. checkCTRLC;
  629. if (s='') or (InOutRes<>0) then exit;
  630. tmpStr:=s;
  631. for j:=1 to length(tmpStr) do
  632. if tmpStr[j]='\' then tmpStr[j]:='/';
  633. move(tmpStr[1],buffer,length(tmpStr));
  634. buffer[length(tmpStr)]:=#0;
  635. tmpLock:=dos_CreateDir(buffer);
  636. if tmpLock=0 then begin
  637. dosError2InOut(dos_IoErr);
  638. exit;
  639. end;
  640. dos_UnLock(tmpLock);
  641. end;
  642. procedure rmdir(const s : string);[IOCheck];
  643. var
  644. buffer : array[0..255] of char;
  645. j : Integer;
  646. tmpStr : string;
  647. begin
  648. checkCTRLC;
  649. if (s='.') then InOutRes:=16;
  650. If (s='') or (InOutRes<>0) then exit;
  651. tmpStr:=s;
  652. for j:=1 to length(tmpStr) do
  653. if tmpStr[j] = '\' then tmpStr[j] := '/';
  654. move(tmpStr[1],buffer,length(tmpStr));
  655. buffer[length(tmpStr)]:=#0;
  656. if not dos_DeleteFile(buffer) then
  657. dosError2InOut(dos_IoErr);
  658. end;
  659. procedure chdir(const s : string);[IOCheck];
  660. var
  661. buffer : array[0..255] of char;
  662. alock : LongInt;
  663. FIB : PFileInfoBlock;
  664. j : Integer;
  665. tmpStr : string;
  666. begin
  667. checkCTRLC;
  668. If (s='') or (InOutRes<>0) then exit;
  669. tmpStr:=s;
  670. for j:=1 to length(tmpStr) do
  671. if tmpStr[j]='\' then tmpStr[j]:='/';
  672. { Return parent directory }
  673. if s='..' then begin
  674. getdir(0,tmpStr);
  675. j:=length(tmpStr);
  676. { Look through the previous paths }
  677. while (tmpStr[j]<>'/') and (tmpStr[j]<>':') and (j>0) do
  678. dec(j);
  679. if j>0 then
  680. tmpStr:=copy(tmpStr,1,j);
  681. end;
  682. alock:=0;
  683. move(tmpStr[1],buffer,length(tmpStr));
  684. buffer[length(tmpStr)]:=#0;
  685. { Changing the directory is a pretty complicated affair }
  686. { 1) Obtain a lock on the directory }
  687. { 2) CurrentDir the lock }
  688. alock:=dos_Lock(buffer,SHARED_LOCK);
  689. if alock=0 then begin
  690. dosError2InOut(dos_IoErr);
  691. exit;
  692. end;
  693. FIB:=nil;
  694. new(FIB);
  695. if (dos_Examine(alock,FIB)=True) and (FIB^.fib_DirEntryType>0) then begin
  696. alock := dos_CurrentDir(alock);
  697. if MOS_OrigDir=0 then begin
  698. MOS_OrigDir:=alock;
  699. alock:=0;
  700. end;
  701. end;
  702. if alock<>0 then dos_Unlock(alock);
  703. if assigned(FIB) then dispose(FIB)
  704. end;
  705. procedure GetDir (DriveNr: byte; var Dir: ShortString);
  706. var tmpbuf: array[0..255] of char;
  707. begin
  708. checkCTRLC;
  709. Dir:='';
  710. if not dos_GetCurrentDirName(tmpbuf,256) then
  711. dosError2InOut(dos_IoErr)
  712. else
  713. Dir:=strpas(tmpbuf);
  714. end;
  715. {****************************************************************************
  716. Low level File Routines
  717. All these functions can set InOutRes on errors
  718. ****************************************************************************}
  719. { close a file from the handle value }
  720. procedure do_close(handle : longint);
  721. begin
  722. RemoveFromList(MOS_fileList,handle);
  723. { Do _NOT_ check CTRL_C on Close, because it will conflict
  724. with System_Exit! }
  725. if not dos_Close(handle) then
  726. dosError2InOut(dos_IoErr);
  727. end;
  728. procedure do_erase(p : pchar);
  729. begin
  730. checkCTRLC;
  731. if not dos_DeleteFile(p) then
  732. dosError2InOut(dos_IoErr);
  733. end;
  734. procedure do_rename(p1,p2 : pchar);
  735. begin
  736. checkCTRLC;
  737. if not dos_Rename(p1,p2) then
  738. dosError2InOut(dos_IoErr);
  739. end;
  740. function do_write(h:longint; addr: pointer; len: longint) : longint;
  741. var dosResult: LongInt;
  742. begin
  743. checkCTRLC;
  744. do_write:=0;
  745. if len<=0 then exit;
  746. dosResult:=dos_Write(h,addr,len);
  747. if dosResult<0 then begin
  748. dosError2InOut(dos_IoErr);
  749. end else begin
  750. do_write:=dosResult;
  751. end;
  752. end;
  753. function do_read(h:longint; addr: pointer; len: longint) : longint;
  754. var dosResult: LongInt;
  755. begin
  756. checkCTRLC;
  757. do_read:=0;
  758. if len<=0 then exit;
  759. dosResult:=dos_Read(h,addr,len);
  760. if dosResult<0 then begin
  761. dosError2InOut(dos_IoErr);
  762. end else begin
  763. do_read:=dosResult;
  764. end
  765. end;
  766. function do_filepos(handle : longint) : longint;
  767. var dosResult: LongInt;
  768. begin
  769. checkCTRLC;
  770. do_filepos:=0;
  771. { Seeking zero from OFFSET_CURRENT to find out where we are }
  772. dosResult:=dos_Seek(handle,0,OFFSET_CURRENT);
  773. if dosResult<0 then begin
  774. dosError2InOut(dos_IoErr);
  775. end else begin
  776. do_filepos:=dosResult;
  777. end;
  778. end;
  779. procedure do_seek(handle,pos : longint);
  780. begin
  781. checkCTRLC;
  782. { Seeking from OFFSET_BEGINNING }
  783. if dos_Seek(handle,pos,OFFSET_BEGINNING)<0 then
  784. dosError2InOut(dos_IoErr);
  785. end;
  786. function do_seekend(handle:longint):longint;
  787. var dosResult: LongInt;
  788. begin
  789. checkCTRLC;
  790. do_seekend:=0;
  791. { Seeking to OFFSET_END }
  792. dosResult:=dos_Seek(handle,0,OFFSET_END);
  793. if dosResult<0 then begin
  794. dosError2InOut(dos_IoErr);
  795. end else begin
  796. do_seekend:=dosResult;
  797. end
  798. end;
  799. function do_filesize(handle : longint) : longint;
  800. var currfilepos: longint;
  801. begin
  802. checkCTRLC;
  803. currfilepos:=do_filepos(handle);
  804. { We have to do this twice, because seek returns the OLD position }
  805. do_filesize:=do_seekend(handle);
  806. do_filesize:=do_seekend(handle);
  807. do_seek(handle,currfilepos)
  808. end;
  809. { truncate at a given position }
  810. procedure do_truncate (handle,pos:longint);
  811. begin
  812. checkCTRLC;
  813. { Seeking from OFFSET_BEGINNING }
  814. if dos_SetFileSize(handle,pos,OFFSET_BEGINNING)<0 then
  815. dosError2InOut(dos_IoErr);
  816. end;
  817. procedure do_open(var f;p:pchar;flags:longint);
  818. {
  819. filerec and textrec have both handle and mode as the first items so
  820. they could use the same routine for opening/creating.
  821. when (flags and $10) the file will be append
  822. when (flags and $100) the file will be truncate/rewritten
  823. when (flags and $1000) there is no check for close (needed for textfiles)
  824. }
  825. var
  826. i,j : LongInt;
  827. openflags : LongInt;
  828. path : String;
  829. buffer : array[0..255] of Char;
  830. index : Integer;
  831. s : String;
  832. begin
  833. path:=strpas(p);
  834. for index:=1 to length(path) do
  835. if path[index]='\' then path[index]:='/';
  836. { remove any dot characters and replace by their current }
  837. { directory equivalent. }
  838. { look for parent directory }
  839. if pos('../',path) = 1 then
  840. begin
  841. delete(path,1,3);
  842. getdir(0,s);
  843. j:=length(s);
  844. while (s[j]<>'/') and (s[j]<>':') and (j>0) do
  845. dec(j);
  846. if j > 0 then
  847. s:=copy(s,1,j);
  848. path:=s+path;
  849. end
  850. else
  851. { look for current directory }
  852. if pos('./',path) = 1 then
  853. begin
  854. delete(path,1,2);
  855. getdir(0,s);
  856. if (s[length(s)]<>'/') and (s[length(s)]<>':') then
  857. s:=s+'/';
  858. path:=s+path;
  859. end;
  860. move(path[1],buffer,length(path));
  861. buffer[length(path)]:=#0;
  862. { close first if opened }
  863. if ((flags and $10000)=0) then
  864. begin
  865. case filerec(f).mode of
  866. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  867. fmclosed : ;
  868. else begin
  869. inoutres:=102; {not assigned}
  870. exit;
  871. end;
  872. end;
  873. end;
  874. { reset file handle }
  875. filerec(f).handle:=UnusedHandle;
  876. { convert filemode to filerec modes }
  877. { READ/WRITE on existing file }
  878. { RESET/APPEND }
  879. openflags := 1005;
  880. case (flags and 3) of
  881. 0 : filerec(f).mode:=fminput;
  882. 1 : filerec(f).mode:=fmoutput;
  883. 2 : filerec(f).mode:=fminout;
  884. end;
  885. { rewrite (create a new file) }
  886. if (flags and $1000)<>0 then openflags := 1006;
  887. { empty name is special }
  888. if p[0]=#0 then
  889. begin
  890. case filerec(f).mode of
  891. fminput :
  892. filerec(f).handle:=StdInputHandle;
  893. fmappend,
  894. fmoutput : begin
  895. filerec(f).handle:=StdOutputHandle;
  896. filerec(f).mode:=fmoutput; {fool fmappend}
  897. end;
  898. end;
  899. exit;
  900. end;
  901. i:=dos_Open(buffer,openflags);
  902. if i=0 then
  903. begin
  904. dosError2InOut(dos_IoErr);
  905. end else begin
  906. AddToList(MOS_fileList,i);
  907. filerec(f).handle:=i;
  908. end;
  909. { append mode }
  910. if ((Flags and $100)<>0) and (FileRec(F).Handle<>UnusedHandle) then
  911. begin
  912. do_seekend(filerec(f).handle);
  913. filerec(f).mode:=fmoutput; {fool fmappend}
  914. end;
  915. end;
  916. function do_isdevice(handle:longint):boolean;
  917. begin
  918. if (handle=StdOutputHandle) or (handle=StdInputHandle) or
  919. (handle=StdErrorHandle) then
  920. do_isdevice:=True
  921. else
  922. do_isdevice:=False;
  923. end;
  924. {*****************************************************************************
  925. UnTyped File Handling
  926. *****************************************************************************}
  927. {$i file.inc}
  928. {*****************************************************************************
  929. Typed File Handling
  930. *****************************************************************************}
  931. {$i typefile.inc}
  932. {*****************************************************************************
  933. Text File Handling
  934. *****************************************************************************}
  935. {$I text.inc}
  936. { MorphOS specific startup }
  937. procedure SysInitMorphOS;
  938. var self: PProcess;
  939. begin
  940. self:=PProcess(FindTask(nil));
  941. if self^.pr_CLI=0 then begin
  942. { if we're running from Ambient/Workbench, we catch its message }
  943. WaitPort(@self^.pr_MsgPort);
  944. MOS_ambMsg:=GetMsg(@self^.pr_MsgPort);
  945. end;
  946. MOS_DOSBase:=OpenLibrary('dos.library',50);
  947. if MOS_DOSBase=nil then Halt(1);
  948. MOS_UtilityBase:=OpenLibrary('utility.library',50);
  949. if MOS_UtilityBase=nil then Halt(1);
  950. { Creating the memory pool for growing heap }
  951. MOS_heapPool:=CreatePool(MEMF_FAST,growheapsize2,growheapsize1);
  952. if MOS_heapPool=nil then Halt(1);
  953. if MOS_ambMsg=nil then begin
  954. StdInputHandle:=dos_Input;
  955. StdOutputHandle:=dos_Output;
  956. end else begin
  957. MOS_ConHandle:=dos_Open(MOS_ConName,1005);
  958. if MOS_ConHandle<>0 then begin
  959. StdInputHandle:=MOS_ConHandle;
  960. StdOutputHandle:=MOS_ConHandle;
  961. end else
  962. Halt(1);
  963. end;
  964. end;
  965. procedure SysInitStdIO;
  966. begin
  967. OpenStdIO(Input,fmInput,StdInputHandle);
  968. OpenStdIO(Output,fmOutput,StdOutputHandle);
  969. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  970. { * MorphOS doesn't have a separate stderr, just like AmigaOS (???) * }
  971. StdErrorHandle:=StdOutputHandle;
  972. // OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  973. end;
  974. begin
  975. IsConsole := TRUE;
  976. IsLibrary := FALSE;
  977. StackLength := InitialStkLen;
  978. StackBottom := Sptr - StackLength;
  979. { OS specific startup }
  980. MOS_ambMsg:=nil;
  981. MOS_origDir:=0;
  982. MOS_fileList:=nil;
  983. envp:=nil;
  984. SysInitMorphOS;
  985. { Set up signals handlers }
  986. // InstallSignals;
  987. { Setup heap }
  988. InitHeap;
  989. SysInitExceptions;
  990. { Setup stdin, stdout and stderr }
  991. SysInitStdIO;
  992. { Reset IO Error }
  993. InOutRes:=0;
  994. { Arguments }
  995. GenerateArgs;
  996. (* This should be changed to a real value during *)
  997. (* thread driver initialization if appropriate. *)
  998. ThreadID := 1;
  999. {$ifdef HASVARIANT}
  1000. initvariantmanager;
  1001. {$endif HASVARIANT}
  1002. end.
  1003. {
  1004. $Log$
  1005. Revision 1.15 2004-06-23 13:27:32 karoly
  1006. * fixed system unit for the new heap manager
  1007. Revision 1.14 2004/06/17 16:16:14 peter
  1008. * New heapmanager that releases memory back to the OS, donated
  1009. by Micha Nelissen
  1010. Revision 1.13 2004/06/13 22:50:47 karoly
  1011. * cleanup and changes to use new includes
  1012. Revision 1.12 2004/06/06 23:31:13 karoly
  1013. * fixed dos_UnLockDosList from being nonsense, and some cleanup
  1014. Revision 1.11 2004/06/06 19:18:05 karoly
  1015. + added support for paramstr(0)
  1016. Revision 1.10 2004/06/05 19:49:19 karoly
  1017. + added console I/O support when running from Ambient
  1018. Revision 1.9 2004/05/12 23:18:54 karoly
  1019. * fixed do_read and dos_Read from being nonsense
  1020. Revision 1.8 2004/05/12 20:26:04 karoly
  1021. + added syscalls and structures necessary for DOS unit
  1022. Revision 1.7 2004/05/12 15:34:16 karoly
  1023. * fixed startup code from endless wait when not started from Ambient
  1024. Revision 1.6 2004/05/09 14:42:59 karoly
  1025. * again, few more new things added
  1026. Revision 1.5 2004/05/09 02:02:42 karoly
  1027. * more things got implemented
  1028. Revision 1.4 2004/05/02 02:06:57 karoly
  1029. + most of file I/O calls implemented
  1030. Revision 1.3 2004/05/01 15:09:47 karoly
  1031. * first working system unit (very limited yet)
  1032. Revision 1.2  2004/04/08 06:28:29  karoly
  1033. * first steps to have a morphos system unit
  1034. Revision 1.1 2004/02/13 07:19:53 karoly
  1035. * quick hack from Linux system unit
  1036. }