sysamiga.pas 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 by the Free Pascal development team.
  5. Some parts taken from
  6. Marcel Timmermans - Modula 2 Compiler
  7. Nils Sjoholm - Amiga porter
  8. See the file COPYING.FPC, included in this distribution,
  9. for details about the copyright.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. **********************************************************************}
  14. unit sysamiga;
  15. { Things left to do : }
  16. { - Fix Truncate!! }
  17. {$I os.inc}
  18. { AmigaOS uses character #10 as eoln only }
  19. {$DEFINE SHORT_LINEBREAK}
  20. interface
  21. { used for single computations }
  22. const BIAS4 = $7f-1;
  23. {$I systemh.inc}
  24. {$I heaph.inc}
  25. const
  26. UnusedHandle : longint = -1;
  27. StdInputHandle : longint = 0;
  28. StdOutputHandle : longint = 0;
  29. StdErrorHandle : longint = 0;
  30. argc : longint = 0;
  31. _ExecBase:longint = $4;
  32. _WorkbenchMsg : longint = 0;
  33. intuitionname : pchar = 'intuition.library';
  34. dosname : pchar = 'dos.library';
  35. utilityname : pchar = 'utility.library';
  36. _IntuitionBase : pointer = nil; { intuition library pointer }
  37. _DosBase : pointer = nil; { DOS library pointer }
  38. _UtilityBase : pointer = nil; { utiity library pointer }
  39. var
  40. OrigDir : Longint;
  41. implementation
  42. {$I exec.inc}
  43. TYPE
  44. TDateStamp = packed record
  45. ds_Days : Longint; { Number of days since Jan. 1, 1978 }
  46. ds_Minute : Longint; { Number of minutes past midnight }
  47. ds_Tick : Longint; { Number of ticks past minute }
  48. end;
  49. PDateStamp = ^TDateStamp;
  50. PFileInfoBlock = ^TfileInfoBlock;
  51. TFileInfoBlock = packed record
  52. fib_DiskKey : Longint;
  53. fib_DirEntryType : Longint;
  54. { Type of Directory. If < 0, then a plain file.
  55. If > 0 a directory }
  56. fib_FileName : Array [0..107] of Char;
  57. { Null terminated. Max 30 chars used for now }
  58. fib_Protection : Longint;
  59. { bit mask of protection, rwxd are 3-0. }
  60. fib_EntryType : Longint;
  61. fib_Size : Longint; { Number of bytes in file }
  62. fib_NumBlocks : Longint; { Number of blocks in file }
  63. fib_Date : TDateStamp; { Date file last changed }
  64. fib_Comment : Array [0..79] of Char;
  65. { Null terminated comment associated with file }
  66. fib_Reserved : Array [0..35] of Char;
  67. end;
  68. TProcess = packed record
  69. pr_Task : TTask;
  70. pr_MsgPort : TMsgPort; { This is BPTR address from DOS functions }
  71. {126} pr_Pad : Word; { Remaining variables on 4 byte boundaries }
  72. {128} pr_SegList : Pointer; { Array of seg lists used by this process }
  73. {132} pr_StackSize : Longint; { Size of process stack in bytes }
  74. {136} pr_GlobVec : Pointer; { Global vector for this process (BCPL) }
  75. {140} pr_TaskNum : Longint; { CLI task number of zero if not a CLI }
  76. {144} pr_StackBase : BPTR; { Ptr to high memory end of process stack }
  77. {148} pr_Result2 : Longint; { Value of secondary result from last call }
  78. {152} pr_CurrentDir : BPTR; { Lock associated with current directory }
  79. {156} pr_CIS : BPTR; { Current CLI Input Stream }
  80. {160} pr_COS : BPTR; { Current CLI Output Stream }
  81. {164} pr_ConsoleTask : Pointer; { Console handler process for current window}
  82. {168} pr_FileSystemTask : Pointer; { File handler process for current drive }
  83. {172} pr_CLI : BPTR; { pointer to ConsoleLineInterpreter }
  84. pr_ReturnAddr : Pointer; { pointer to previous stack frame }
  85. pr_PktWait : Pointer; { Function to be called when awaiting msg }
  86. pr_WindowPtr : Pointer; { Window for error printing }
  87. { following definitions are new with 2.0 }
  88. pr_HomeDir : BPTR; { Home directory of executing program }
  89. pr_Flags : Longint; { flags telling dos about process }
  90. pr_ExitCode : Pointer; { code to call on exit of program OR NULL }
  91. pr_ExitData : Longint; { Passed as an argument to pr_ExitCode. }
  92. pr_Arguments : PChar; { Arguments passed to the process at start }
  93. pr_LocalVars : TMinList; { Local environment variables }
  94. pr_ShellPrivate : Longint; { for the use of the current shell }
  95. pr_CES : BPTR; { Error stream - IF NULL, use pr_COS }
  96. end;
  97. PProcess = ^TProcess;
  98. Const
  99. _LVOFindTask = -294;
  100. _LVOWaitPort = -384;
  101. _LVOGetMsg = -372;
  102. _LVOOpenLibrary = -552;
  103. _LVOCloseLibrary = -414;
  104. _LVOClose = -36;
  105. _LVOOpen = -30;
  106. _LVOIoErr = -132;
  107. _LVOSeek = -66;
  108. _LVODeleteFile = -72;
  109. _LVORename = -78;
  110. _LVOWrite = -48;
  111. _LVORead = -42;
  112. _LVOCreateDir = -120;
  113. _LVOSetCurrentDirName = -558;
  114. _LVOGetCurrentDirName = -564;
  115. _LVOInput = -54;
  116. _LVOOutput = -60;
  117. _LVOUnLock = -90;
  118. _LVOLock = -84;
  119. _LVOCurrentDir = -126;
  120. _LVONameFromLock = -402;
  121. _LVONameFromFH = -408;
  122. _LVOGetProgramName = -576;
  123. _LVOGetProgramDir = -600;
  124. _LVODupLock = -96;
  125. _LVOExamine = -102;
  126. _LVOParentDir = -210;
  127. { Errors from IoErr(), etc. }
  128. ERROR_NO_FREE_STORE = 103;
  129. ERROR_TASK_TABLE_FULL = 105;
  130. ERROR_BAD_TEMPLATE = 114;
  131. ERROR_BAD_NUMBER = 115;
  132. ERROR_REQUIRED_ARG_MISSING = 116;
  133. ERROR_KEY_NEEDS_ARG = 117;
  134. ERROR_TOO_MANY_ARGS = 118;
  135. ERROR_UNMATCHED_QUOTES = 119;
  136. ERROR_LINE_TOO_LONG = 120;
  137. ERROR_FILE_NOT_OBJECT = 121;
  138. ERROR_INVALID_RESIDENT_LIBRARY = 122;
  139. ERROR_NO_DEFAULT_DIR = 201;
  140. ERROR_OBJECT_IN_USE = 202;
  141. ERROR_OBJECT_EXISTS = 203;
  142. ERROR_DIR_NOT_FOUND = 204;
  143. ERROR_OBJECT_NOT_FOUND = 205;
  144. ERROR_BAD_STREAM_NAME = 206;
  145. ERROR_OBJECT_TOO_LARGE = 207;
  146. ERROR_ACTION_NOT_KNOWN = 209;
  147. ERROR_INVALID_COMPONENT_NAME = 210;
  148. ERROR_INVALID_LOCK = 211;
  149. ERROR_OBJECT_WRONG_TYPE = 212;
  150. ERROR_DISK_NOT_VALIDATED = 213;
  151. ERROR_DISK_WRITE_PROTECTED = 214;
  152. ERROR_RENAME_ACROSS_DEVICES = 215;
  153. ERROR_DIRECTORY_NOT_EMPTY = 216;
  154. ERROR_TOO_MANY_LEVELS = 217;
  155. ERROR_DEVICE_NOT_MOUNTED = 218;
  156. ERROR_SEEK_ERROR = 219;
  157. ERROR_COMMENT_TOO_BIG = 220;
  158. ERROR_DISK_FULL = 221;
  159. ERROR_DELETE_PROTECTED = 222;
  160. ERROR_WRITE_PROTECTED = 223;
  161. ERROR_READ_PROTECTED = 224;
  162. ERROR_NOT_A_DOS_DISK = 225;
  163. ERROR_NO_DISK = 226;
  164. ERROR_NO_MORE_ENTRIES = 232;
  165. { added for 1.4 }
  166. ERROR_IS_SOFT_LINK = 233;
  167. ERROR_OBJECT_LINKED = 234;
  168. ERROR_BAD_HUNK = 235;
  169. ERROR_NOT_IMPLEMENTED = 236;
  170. ERROR_RECORD_NOT_LOCKED = 240;
  171. ERROR_LOCK_COLLISION = 241;
  172. ERROR_LOCK_TIMEOUT = 242;
  173. ERROR_UNLOCK_ERROR = 243;
  174. var
  175. Initial: boolean;
  176. errno : word;
  177. {$I system.inc}
  178. {$I lowmath.inc}
  179. { ************************ AMIGAOS STUB ROUTINES ************************* }
  180. procedure DateStamp(var ds : tDateStamp);
  181. begin
  182. asm
  183. MOVE.L A6,-(A7)
  184. MOVE.L ds,d1
  185. { LAST THING TO SETUP SHOULD BE A6, otherwise you can }
  186. { not accept local variable, nor any parameters! :) }
  187. MOVE.L _DOSBase,A6
  188. JSR -192(A6)
  189. MOVE.L (A7)+,A6
  190. end;
  191. end;
  192. { UNLOCK the BPTR pointed to in L }
  193. Procedure Unlock(alock: longint);
  194. Begin
  195. asm
  196. move.l alock,d1
  197. move.l a6,d6 { save base pointer }
  198. move.l _DosBase,a6
  199. jsr _LVOUnlock(a6)
  200. move.l d6,a6 { restore base pointer }
  201. end;
  202. end;
  203. { Change to the directory pointed to in the lock }
  204. Function CurrentDir(alock : longint) : longint;
  205. Begin
  206. asm
  207. move.l alock,d1
  208. move.l a6,d6 { save base pointer }
  209. move.l _DosBase,a6
  210. jsr _LVOCurrentDir(a6)
  211. move.l d6,a6 { restore base pointer }
  212. move.l d0,@Result
  213. end;
  214. end;
  215. { Duplicate a lock }
  216. Function DupLock(alock: longint): Longint;
  217. Begin
  218. asm
  219. move.l alock,d1
  220. move.l a6,d6 { save base pointer }
  221. move.l _DosBase,a6
  222. jsr _LVODupLock(a6)
  223. move.l d6,a6 { restore base pointer }
  224. move.l d0,@Result
  225. end;
  226. end;
  227. { Returns a lock on the directory was loaded from }
  228. Function GetProgramLock: longint;
  229. Begin
  230. asm
  231. move.l a6,d6 { save base pointer }
  232. move.l _DosBase,a6
  233. jsr _LVOGetProgramDir(a6)
  234. move.l d6,a6 { restore base pointer }
  235. move.l d0,@Result
  236. end;
  237. end;
  238. Function Examine(alock :longint; var fib: TFileInfoBlock) : Boolean;
  239. Begin
  240. asm
  241. move.l d2,-(sp)
  242. move.l fib,d2 { pointer to FIB }
  243. move.l alock,d1
  244. move.l a6,d6 { save base pointer }
  245. move.l _DosBase,a6
  246. jsr _LVOExamine(a6)
  247. move.l d6,a6 { restore base pointer }
  248. tst.l d0
  249. bne @success
  250. bra @end
  251. @success:
  252. move.b #1,d0
  253. @end:
  254. move.b d0,@Result
  255. move.l (sp)+,d2
  256. end;
  257. end;
  258. { Returns the parent directory of a lock }
  259. Function ParentDir(alock : longint): longint;
  260. Begin
  261. asm
  262. move.l alock,d1
  263. move.l a6,d6 { save base pointer }
  264. move.l _DosBase,a6
  265. jsr _LVOParentDir(a6)
  266. move.l d6,a6 { restore base pointer }
  267. move.l d0,@Result
  268. end;
  269. end;
  270. Function FindTask(p : PChar): PProcess;
  271. Begin
  272. asm
  273. move.l a6,d6 { Save base pointer }
  274. move.l p,d0
  275. move.l d0,a1
  276. move.l _ExecBase,a6
  277. jsr _LVOFindTask(a6)
  278. move.l d6,a6 { Restore base pointer }
  279. move.l d0,@Result
  280. end;
  281. end;
  282. {$S-}
  283. Procedure stack_check; assembler;
  284. { Check for local variable allocation }
  285. { On Entry -> d0 : size of local stack we are trying to allocate }
  286. asm
  287. XDEF STACKCHECK
  288. move.l sp,d1 { get value of stack pointer }
  289. { We must add some security, because Writing the RunError strings }
  290. { requires a LOT of stack space (at least 1030 bytes!) }
  291. add.l #2048,d0
  292. sub.l d0,d1 { sp - stack_size }
  293. move.l _ExecBase,a0
  294. move.l 276(A0),A0 { ExecBase.thisTask }
  295. { if allocated stack_pointer - splower <= 0 then stack_ovf }
  296. cmp.l 58(A0),D1 { Task.SpLower }
  297. bgt @Ok
  298. move.l #202,d0
  299. jsr HALT_ERROR { stack overflow }
  300. @Ok:
  301. end;
  302. { Converts an AMIGAOS error code to a TP compatible error code }
  303. Procedure Error2InOut;
  304. Begin
  305. case errno of
  306. ERROR_BAD_NUMBER,
  307. ERROR_ACTION_NOT_KNOWN,
  308. ERROR_NOT_IMPLEMENTED : InOutRes := 1;
  309. ERROR_OBJECT_NOT_FOUND : InOutRes := 2;
  310. ERROR_DIR_NOT_FOUND : InOutRes := 3;
  311. ERROR_DISK_WRITE_PROTECTED : InOutRes := 150;
  312. ERROR_OBJECT_WRONG_TYPE : InOutRes := 151;
  313. ERROR_OBJECT_EXISTS,
  314. ERROR_DELETE_PROTECTED,
  315. ERROR_WRITE_PROTECTED,
  316. ERROR_READ_PROTECTED,
  317. ERROR_OBJECT_IN_USE,
  318. ERROR_DIRECTORY_NOT_EMPTY : InOutRes := 5;
  319. ERROR_NO_MORE_ENTRIES : InOutRes := 18;
  320. ERROR_RENAME_ACROSS_DEVICES : InOutRes := 17;
  321. ERROR_DISK_FULL : InOutRes := 101;
  322. ERROR_INVALID_RESIDENT_LIBRARY : InoutRes := 153;
  323. ERROR_BAD_HUNK : InOutRes := 153;
  324. ERROR_NOT_A_DOS_DISK : InOutRes := 157;
  325. ERROR_NO_DISK,
  326. ERROR_DISK_NOT_VALIDATED,
  327. ERROR_DEVICE_NOT_MOUNTED : InOutRes := 152;
  328. ERROR_SEEK_ERROR : InOutRes := 156;
  329. ERROR_LOCK_COLLISION,
  330. ERROR_LOCK_TIMEOUT,
  331. ERROR_UNLOCK_ERROR,
  332. ERROR_INVALID_LOCK,
  333. ERROR_INVALID_COMPONENT_NAME,
  334. ERROR_BAD_STREAM_NAME,
  335. ERROR_FILE_NOT_OBJECT : InOutRes := 6;
  336. else
  337. InOutres := errno;
  338. end;
  339. errno:=0;
  340. end;
  341. procedure CloseLibrary(lib : pointer);
  342. { Close the library pointed to in lib }
  343. Begin
  344. asm
  345. MOVE.L A6,-(A7)
  346. MOVE.L lib,a1
  347. MOVE.L _ExecBase,A6
  348. JSR _LVOCloseLibrary(A6)
  349. MOVE.L (A7)+,A6
  350. end;
  351. end;
  352. Function KickVersion: word; assembler;
  353. asm
  354. move.l _ExecBase, a0 { Get Exec Base }
  355. move.w 20(a0), d0 { Return version - version at this offset }
  356. end;
  357. procedure halt(errnum : byte);
  358. begin
  359. { WE can only FLUSH the stdio }
  360. { if the handles have correctly }
  361. { been set. }
  362. { No exit procedures exist }
  363. { if in initial state }
  364. If NOT Initial then
  365. Begin
  366. do_exit;
  367. flush(stderr);
  368. end;
  369. if (OrigDir <> 0) then
  370. Begin
  371. Unlock(CurrentDir(OrigDir));
  372. OrigDir := 0;
  373. end;
  374. { close the libraries }
  375. If _UtilityBase <> nil then
  376. Begin
  377. CloseLibrary(_UtilityBase);
  378. end;
  379. If _DosBase <> nil then
  380. Begin
  381. CloseLibrary(_DosBase);
  382. end;
  383. If _IntuitionBase <> nil then
  384. Begin
  385. CloseLibrary(_IntuitionBase);
  386. end;
  387. asm
  388. clr.l d0
  389. move.b errnum,d0
  390. move.l STKPTR,sp
  391. rts
  392. end;
  393. end;
  394. { ************************ PARAMCOUNT/PARAMSTR *************************** }
  395. function paramcount : longint;
  396. Begin
  397. paramcount := argc;
  398. end;
  399. function args : pointer; assembler;
  400. asm
  401. move.l __ARGS,d0
  402. end;
  403. Function GetParamCount(const p: pchar): longint;
  404. var
  405. i: word;
  406. count: word;
  407. Begin
  408. i:=0;
  409. count:=0;
  410. while p[count] <> #0 do
  411. Begin
  412. if (p[count] <> ' ') and (p[count] <> #9) and (p[count] <> #0) then
  413. Begin
  414. i:=i+1;
  415. while (p[count] <> ' ') and (p[count] <> #9) and (p[count] <> #0) do
  416. count:=count+1;
  417. end;
  418. if p[count] = #0 then break;
  419. count:=count+1;
  420. end;
  421. GetParamCount:=longint(i);
  422. end;
  423. Function GetParam(index: word; const p : pchar): string;
  424. { On Entry: index = string index to correct parameter }
  425. { On exit: = correct character index into pchar array }
  426. { Returns correct index to command line argument }
  427. var
  428. count: word;
  429. localindex: word;
  430. l: byte;
  431. temp: string;
  432. Begin
  433. temp:='';
  434. count := 0;
  435. { first index is one }
  436. localindex := 1;
  437. l:=0;
  438. While p[count] <> #0 do
  439. Begin
  440. if (p[count] <> ' ') and (p[count] <> #9) then
  441. Begin
  442. if localindex = index then
  443. Begin
  444. while (p[count] <> #0) and (p[count] <> ' ') and (p[count] <> #9) and (l < 256) do
  445. Begin
  446. temp:=temp+p[count];
  447. l:=l+1;
  448. count:=count+1;
  449. end;
  450. temp[0]:=char(l);
  451. GetParam:=temp;
  452. exit;
  453. end;
  454. { Point to next argument in list }
  455. while (p[count] <> #0) and (p[count] <> ' ') and (p[count] <> #9) do
  456. Begin
  457. count:=count+1;
  458. end;
  459. localindex:=localindex+1;
  460. end;
  461. if p[count] = #0 then break;
  462. count:=count+1;
  463. end;
  464. GetParam:=temp;
  465. end;
  466. Function GetProgramDir : String;
  467. var
  468. s1: string;
  469. alock: longint;
  470. counter : byte;
  471. Begin
  472. FillChar(@s1,255,#0);
  473. { GetLock of program directory }
  474. asm
  475. move.l a6,d6 { save a6 }
  476. move.l _DOSBase,a6
  477. jsr _LVOGetProgramDir(a6)
  478. move.l d6,a6 { restore a6 }
  479. move.l d0,alock { save the lock }
  480. end;
  481. if alock <> 0 then
  482. Begin
  483. { Get the name from the lock! }
  484. asm
  485. movem.l d2/d3,-(sp) { save used registers }
  486. move.l alock,d1
  487. lea s1,a0 { Get pointer to string! }
  488. move.l a0,d2
  489. add.l #1,d2 { let us point past the length byte! }
  490. move.l #255,d3
  491. move.l a6,d6 { save a6 }
  492. move.l _DOSBase,a6
  493. jsr _LVONameFromLock(a6)
  494. move.l d6,a6 { restore a6 }
  495. movem.l (sp)+,d2/d3
  496. end;
  497. { no check out the length of the string }
  498. counter := 1;
  499. while s1[counter] <> #0 do
  500. Inc(counter);
  501. s1[0] := char(counter-1);
  502. GetProgramDir := s1;
  503. end
  504. else
  505. GetProgramDir := '';
  506. end;
  507. Function GetProgramName : string;
  508. { Returns ONLY the program name }
  509. { There seems to be a bug in v39 since if the program is not }
  510. { called from its home directory the program name will also }
  511. { contain the path! }
  512. var
  513. s1: string;
  514. counter : byte;
  515. Begin
  516. FillChar(@s1,255,#0);
  517. asm
  518. move.l d2,-(sp) { Save used register }
  519. lea s1,a0 { Get pointer to string! }
  520. move.l a0,d1
  521. add.l #1,d1 { point to correct offset }
  522. move.l #255,d2
  523. move.l a6,d6 { save a6 }
  524. move.l _DOSBase,a6
  525. jsr _LVOGetProgramName(a6)
  526. move.l d6,a6 { restore a6 }
  527. move.l (sp)+,d2 { restore saved register }
  528. end;
  529. { no check out and assign the length of the string }
  530. counter := 1;
  531. while s1[counter] <> #0 do
  532. Inc(counter);
  533. s1[0] := char(counter-1);
  534. { now remove any component path which should not be there }
  535. for counter:=length(s1) downto 1 do
  536. if (s1[counter] = '/') or (s1[counter] = ':') then break;
  537. { readjust counterv to point to character }
  538. if counter <> 1 then
  539. Inc(counter);
  540. GetProgramName:=copy(s1,counter,length(s1));
  541. end;
  542. function paramstr(l : longint) : string;
  543. var
  544. p : pchar;
  545. s1 : string;
  546. begin
  547. { -> Call AmigaOS GetProgramName }
  548. if l = 0 then
  549. Begin
  550. s1 := GetProgramDir;
  551. { If this is a root, then simply don't add '/' }
  552. if s1[length(s1)] = ':' then
  553. paramstr:=s1+GetProgramName
  554. else
  555. { add backslash directory }
  556. paramstr:=s1+'/'+GetProgramName
  557. end
  558. else
  559. if (l>0) and (l<=paramcount) then
  560. begin
  561. p:=args;
  562. paramstr:=GetParam(word(l),p);
  563. end
  564. else paramstr:='';
  565. end;
  566. { ************************************************************************ }
  567. procedure randomize;
  568. var
  569. hl : longint;
  570. time : TDateStamp;
  571. begin
  572. DateStamp(time);
  573. randseed:=time.ds_tick;
  574. end;
  575. { This routine is used to grow the heap. }
  576. { But here we do a trick, we say that the }
  577. { heap cannot be regrown! }
  578. function sbrk( size: longint): longint;
  579. { on exit -1 = if fails. }
  580. Begin
  581. sbrk:=-1;
  582. end;
  583. {$I heap.inc}
  584. {****************************************************************************
  585. Low Level File Routines
  586. ****************************************************************************}
  587. procedure do_close(h : longint);
  588. begin
  589. asm
  590. move.l h,d1
  591. move.l a6,d6 { save a6 }
  592. move.l _DOSBase,a6
  593. jsr _LVOClose(a6)
  594. move.l d6,a6 { restore a6 }
  595. end;
  596. end;
  597. function do_isdevice(handle:longint):boolean;
  598. begin
  599. if (handle=stdoutputhandle) or (handle=stdinputhandle) or
  600. (handle=stderrorhandle) then
  601. do_isdevice:=TRUE
  602. else
  603. do_isdevice:=FALSE;
  604. end;
  605. procedure do_erase(p : pchar);
  606. begin
  607. asm
  608. move.l a6,d6 { save a6 }
  609. move.l p,d1
  610. move.l _DOSBase,a6
  611. jsr _LVODeleteFile(a6)
  612. tst.l d0 { zero = failure }
  613. bne @noerror
  614. jsr _LVOIoErr(a6)
  615. move.w d0,errno
  616. @noerror:
  617. move.l d6,a6 { restore a6 }
  618. end;
  619. if errno <> 0 then
  620. Error2InOut;
  621. end;
  622. procedure do_rename(p1,p2 : pchar);
  623. begin
  624. asm
  625. move.l a6,d6 { save a6 }
  626. move.l d2,-(sp) { save d2 }
  627. move.l p1,d1
  628. move.l p2,d2
  629. move.l _DOSBase,a6
  630. jsr _LVORename(a6)
  631. move.l (sp)+,d2 { restore d2 }
  632. tst.l d0
  633. bne @dosreend { if zero = error }
  634. jsr _LVOIoErr(a6)
  635. move.w d0,errno
  636. @dosreend:
  637. move.l d6,a6 { restore a6 }
  638. end;
  639. if errno <> 0 then
  640. Error2InOut;
  641. end;
  642. function do_write(h,addr,len : longint) : longint;
  643. begin
  644. if len <= 0 then
  645. Begin
  646. do_write:=0;
  647. exit;
  648. end;
  649. asm
  650. move.l a6,d6
  651. movem.l d2/d3,-(sp)
  652. move.l h,d1 { we must of course set up the }
  653. move.l addr,d2 { parameters BEFORE getting }
  654. move.l len,d3 { _DOSBase }
  655. move.l _DOSBase,a6
  656. jsr _LVOWrite(a6)
  657. movem.l (sp)+,d2/d3
  658. cmp.l #-1,d0
  659. bne @doswrend { if -1 = error }
  660. jsr _LVOIoErr(a6)
  661. move.w d0,errno
  662. bra @doswrend2
  663. @doswrend:
  664. { we must restore the base pointer before setting the result }
  665. move.l d6,a6
  666. move.l d0,@RESULT
  667. bra @end
  668. @doswrend2:
  669. move.l d6,a6
  670. @end:
  671. end;
  672. If errno <> 0 then
  673. Error2InOut;
  674. end;
  675. function do_read(h,addr,len : longint) : longint;
  676. begin
  677. if len <= 0 then
  678. Begin
  679. do_read:=0;
  680. exit;
  681. end;
  682. asm
  683. move.l a6,d6
  684. movem.l d2/d3,-(sp)
  685. move.l h,d1 { we must set up aparamters BEFORE }
  686. move.l addr,d2 { setting up a6 for the OS call }
  687. move.l len,d3
  688. move.l _DOSBase,a6
  689. jsr _LVORead(a6)
  690. movem.l (sp)+,d2/d3
  691. cmp.l #-1,d0
  692. bne @doswrend { if -1 = error }
  693. jsr _LVOIoErr(a6)
  694. move.w d0,errno
  695. bra @doswrend2
  696. @doswrend:
  697. { to store a result for the function }
  698. { we must of course first get back the}
  699. { base pointer! }
  700. move.l d6,a6
  701. move.l d0,@RESULT
  702. bra @end
  703. @doswrend2:
  704. move.l d6,a6
  705. @end:
  706. end;
  707. If errno <> 0 then
  708. Error2InOut;
  709. end;
  710. function do_filepos(handle : longint) : longint;
  711. begin
  712. asm
  713. move.l a6,d6
  714. move.l handle,d1
  715. move.l d2,-(sp)
  716. move.l d3,-(sp) { save registers }
  717. clr.l d2 { offset 0 }
  718. move.l #0,d3 { OFFSET_CURRENT }
  719. move.l _DOSBase,a6
  720. jsr _LVOSeek(a6)
  721. move.l (sp)+,d3 { restore registers }
  722. move.l (sp)+,d2
  723. cmp.l #-1,d0 { is there a file access error? }
  724. bne @noerr
  725. jsr _LVOIoErr(a6)
  726. move.w d0,errno
  727. bra @fposend
  728. @noerr:
  729. move.l d6,a6 { restore a6 }
  730. move.l d0,@Result
  731. bra @end
  732. @fposend:
  733. move.l d6,a6 { restore a6 }
  734. @end:
  735. end;
  736. If errno <> 0 then
  737. Error2InOut;
  738. end;
  739. procedure do_seek(handle,pos : longint);
  740. begin
  741. asm
  742. move.l a6,d6
  743. move.l handle,d1
  744. move.l d2,-(sp)
  745. move.l d3,-(sp) { save registers }
  746. move.l pos,d2
  747. { -1 }
  748. move.l #$ffffffff,d3 { OFFSET_BEGINNING }
  749. move.l _DOSBase,a6
  750. jsr _LVOSeek(a6)
  751. move.l (sp)+,d3 { restore registers }
  752. move.l (sp)+,d2
  753. cmp.l #-1,d0 { is there a file access error? }
  754. bne @noerr
  755. jsr _LVOIoErr(a6)
  756. move.w d0,errno
  757. bra @seekend
  758. @noerr:
  759. @seekend:
  760. move.l d6,a6 { restore a6 }
  761. end;
  762. If errno <> 0 then
  763. Error2InOut;
  764. end;
  765. function do_seekend(handle:longint):longint;
  766. begin
  767. asm
  768. { seek from end of file }
  769. move.l a6,d6
  770. move.l handle,d1
  771. move.l d2,-(sp)
  772. move.l d3,-(sp) { save registers }
  773. clr.l d2
  774. move.l #1,d3 { OFFSET_END }
  775. move.l _DOSBase,a6
  776. jsr _LVOSeek(a6)
  777. move.l (sp)+,d3 { restore registers }
  778. move.l (sp)+,d2
  779. cmp.l #-1,d0 { is there a file access error? }
  780. bne @noerr
  781. jsr _LVOIoErr(a6)
  782. move.w d0,errno
  783. bra @seekend
  784. @noerr:
  785. move.l d6,a6 { restore a6 }
  786. move.l d0,@Result
  787. bra @end
  788. @seekend:
  789. move.l d6,a6 { restore a6 }
  790. @end:
  791. end;
  792. If Errno <> 0 then
  793. Error2InOut;
  794. end;
  795. function do_filesize(handle : longint) : longint;
  796. var
  797. aktfilepos : longint;
  798. begin
  799. aktfilepos:=do_filepos(handle);
  800. { We have to do this two times, because seek returns the }
  801. { OLD position }
  802. do_filesize:=do_seekend(handle);
  803. do_filesize:=do_seekend(handle);
  804. do_seek(handle,aktfilepos);
  805. end;
  806. procedure do_truncate (handle,pos:longint);
  807. begin
  808. {!!!!!!!!!!!!}
  809. end;
  810. procedure do_open(var f;p:pchar;flags:longint);
  811. {
  812. filerec and textrec have both handle and mode as the first items so
  813. they could use the same routine for opening/creating.
  814. when (flags and $10) the file will be append
  815. when (flags and $100) the file will be truncate/rewritten
  816. when (flags and $1000) there is no check for close (needed for textfiles)
  817. }
  818. var
  819. i : longint;
  820. oflags: longint;
  821. begin
  822. { close first if opened }
  823. if ((flags and $1000)=0) then
  824. begin
  825. case filerec(f).mode of
  826. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  827. fmclosed : ;
  828. else
  829. begin
  830. inoutres:=102; {not assigned}
  831. exit;
  832. end;
  833. end;
  834. end;
  835. { reset file handle }
  836. filerec(f).handle:=UnusedHandle;
  837. { convert filemode to filerec modes }
  838. { READ/WRITE on existing file }
  839. { RESET/APPEND }
  840. oflags := 1005;
  841. case (flags and 3) of
  842. 0 : begin
  843. filerec(f).mode:=fminput;
  844. end;
  845. 1 : filerec(f).mode:=fmoutput;
  846. 2 : filerec(f).mode:=fminout;
  847. end;
  848. { READ/WRITE mode, create file in all cases }
  849. { REWRITE }
  850. if (flags and $100)<>0 then
  851. begin
  852. filerec(f).mode:=fmoutput;
  853. oflags := 1006;
  854. end
  855. else
  856. { READ/WRITE mode on existing file }
  857. { APPEND }
  858. if (flags and $10)<>0 then
  859. begin
  860. filerec(f).mode:=fmoutput;
  861. oflags := 1005;
  862. end;
  863. { empty name is special }
  864. if p[0]=#0 then
  865. begin
  866. case filerec(f).mode of
  867. fminput : filerec(f).handle:=StdInputHandle;
  868. fmappend,
  869. fmoutput : begin
  870. filerec(f).handle:=StdOutputHandle;
  871. filerec(f).mode:=fmoutput; {fool fmappend}
  872. end;
  873. end;
  874. exit;
  875. end;
  876. asm
  877. move.l a6,d6 { save a6 }
  878. move.l p,d1
  879. move.l oflags,d2 { MODE_READWRITE }
  880. move.l _DOSBase,a6
  881. jsr _LVOOpen(a6)
  882. tst.l d0
  883. bne @noopenerror { on zero an error occured }
  884. jsr _LVOIoErr(a6)
  885. move.w d0,errno
  886. bra @openend
  887. @noopenerror:
  888. move.l d6,a6 { restore a6 }
  889. move.l d0,i { we need the base pointer to access this variable }
  890. bra @end
  891. @openend:
  892. move.l d6,a6 { restore a6 }
  893. @end:
  894. end;
  895. If Errno <> 0 then
  896. Error2InOut;
  897. filerec(f).handle:=i;
  898. if (flags and $10)<>0 then
  899. do_seekend(filerec(f).handle);
  900. end;
  901. {*****************************************************************************
  902. UnTyped File Handling
  903. *****************************************************************************}
  904. {$i file.inc}
  905. {*****************************************************************************
  906. Typed File Handling
  907. *****************************************************************************}
  908. {$i typefile.inc}
  909. {*****************************************************************************
  910. Text File Handling
  911. *****************************************************************************}
  912. {$i text.inc}
  913. {*****************************************************************************
  914. Directory Handling
  915. *****************************************************************************}
  916. procedure mkdir(const s : string);[IOCheck];
  917. var
  918. buffer : array[0..255] of char;
  919. begin
  920. If InOutRes <> 0 then exit;
  921. move(s[1],buffer,length(s));
  922. buffer[length(s)]:=#0;
  923. asm
  924. move.l a6,d6
  925. { we must load the parameters BEFORE setting up the }
  926. { OS call with a6 }
  927. lea buffer,a0
  928. move.l a0,d1
  929. move.l _DosBase,a6
  930. jsr _LVOCreateDir(a6)
  931. tst.l d0
  932. bne @noerror
  933. jsr _LVOIoErr(a6)
  934. move.w d0,errno
  935. bra @end
  936. @noerror:
  937. { Now we must unlock the directory }
  938. { d0 = lock returned by create dir }
  939. move.l d0,d1
  940. jsr _LVOUnlock(a6)
  941. @end:
  942. { restore base pointer }
  943. move.l d6,a6
  944. end;
  945. If errno <> 0 then
  946. Error2InOut;
  947. end;
  948. procedure rmdir(const s : string);[IOCheck];
  949. var
  950. buffer : array[0..255] of char;
  951. begin
  952. If InOutRes <> 0 then exit;
  953. move(s[1],buffer,length(s));
  954. buffer[length(s)]:=#0;
  955. do_erase(buffer);
  956. end;
  957. procedure chdir(const s : string);[IOCheck];
  958. var
  959. buffer : array[0..255] of char;
  960. alock : longint;
  961. FIB :pFileInfoBlock;
  962. begin
  963. If InOutRes <> 0 then exit;
  964. alock := 0;
  965. fib:=nil;
  966. new(fib);
  967. move(s[1],buffer,length(s));
  968. buffer[length(s)]:=#0;
  969. { Changing the directory is a pretty complicated affair }
  970. { 1) Obtain a lock on the directory }
  971. { 2) CurrentDir the lock }
  972. asm
  973. lea buffer,a0
  974. move.l a0,d1 { pointer to buffer in d1 }
  975. move.l d2,-(sp) { save d2 register }
  976. move.l #-2,d2 { ACCESS_READ lock }
  977. move.l a6,d6 { Save base pointer }
  978. move.l _DosBase,a6
  979. jsr _LVOLock(a6){ Lock the directory }
  980. move.l (sp)+,d2 { Restore d2 register }
  981. tst.l d0 { zero = error! }
  982. bne @noerror
  983. jsr _LVOIoErr(a6)
  984. move.w d0,errno
  985. move.l d6,a6 { reset base pointer }
  986. bra @End
  987. @noerror:
  988. move.l d6,a6 { reset base pointer }
  989. move.l d0,alock { save the lock }
  990. @End:
  991. end;
  992. If errno <> 0 then
  993. Begin
  994. Error2InOut;
  995. exit;
  996. end;
  997. if (Examine(alock, fib^) = TRUE) AND (fib^.fib_DirEntryType > 0) then
  998. Begin
  999. alock := CurrentDir(alock);
  1000. if OrigDir = 0 then
  1001. Begin
  1002. OrigDir := alock;
  1003. alock := 0;
  1004. end;
  1005. end;
  1006. if alock <> 0 then
  1007. Unlock(alock);
  1008. if assigned(fib) then dispose(fib);
  1009. end;
  1010. Procedure GetCwd(var path: string);
  1011. var
  1012. lock: longint;
  1013. fib: PfileInfoBlock;
  1014. len : integer;
  1015. newlock : longint;
  1016. elen : integer;
  1017. Process : PProcess;
  1018. Begin
  1019. len := 0;
  1020. path := '';
  1021. fib := nil;
  1022. { By using a pointer instead of a local variable}
  1023. { we are assured that the pointer is aligned on }
  1024. { a dword boundary. }
  1025. new(fib);
  1026. Process := FindTask(nil);
  1027. if (process^.pr_Task.tc_Node.ln_Type = NT_TASK) then
  1028. Begin
  1029. path:='';
  1030. exit;
  1031. end;
  1032. lock := DupLock(process^.pr_CurrentDir);
  1033. if (Lock = 0) then
  1034. Begin
  1035. path:='';
  1036. exit;
  1037. end;
  1038. While (lock <> 0) and (Examine(lock,FIB^) = TRUE) do
  1039. Begin
  1040. elen := strlen(fib^.fib_FileName);
  1041. if (len + elen + 2 > 255) then
  1042. break;
  1043. newlock := ParentDir(lock);
  1044. if (len <> 0) then
  1045. Begin
  1046. if (newlock <> 0) then
  1047. path:='/'+path
  1048. else
  1049. path:=':'+path;
  1050. path:=strpas(fib^.fib_FileName)+path;
  1051. Inc(len);
  1052. end
  1053. else
  1054. Begin
  1055. path:=strpas(fib^.fib_Filename);
  1056. if (newlock = 0) then
  1057. path:=path+':';
  1058. end;
  1059. len := len + elen;
  1060. UnLock(lock);
  1061. lock := newlock;
  1062. end;
  1063. if (lock <> 0) then
  1064. Begin
  1065. UnLock(lock);
  1066. path := '';
  1067. end;
  1068. if assigned(fib) then dispose(fib);
  1069. end;
  1070. procedure getdir(drivenr : byte;var dir : string);
  1071. begin
  1072. GetCwd(dir);
  1073. If errno <> 0 then
  1074. Error2InOut;
  1075. end;
  1076. {*****************************************************************************
  1077. SystemUnit Initialization
  1078. *****************************************************************************}
  1079. Procedure Startup; Assembler;
  1080. asm
  1081. move.l a6,d6 { save a6 }
  1082. move.l (4),a6 { get ExecBase pointer }
  1083. move.l a6,_ExecBase
  1084. suba.l a1,a1
  1085. jsr _LVOFindTask(a6)
  1086. move.l d0,a0
  1087. { Check the stack value }
  1088. { are we running from a CLI? }
  1089. tst.l 172(a0) { 172 = pr_CLI }
  1090. bne @fromCLI
  1091. { we do not support Workbench yet .. }
  1092. move.l d6,a6 { restore a6 }
  1093. move.l #1,d0
  1094. jsr HALT_ERROR
  1095. @fromCLI:
  1096. { Open the following libraries: }
  1097. { Intuition.library }
  1098. { dos.library }
  1099. moveq.l #0,d0
  1100. move.l intuitionname,a1 { directly since it is a pchar }
  1101. jsr _LVOOpenLibrary(a6)
  1102. move.l d0,_IntuitionBase
  1103. beq @exitprg
  1104. moveq.l #0,d0
  1105. move.l utilityname,a1 { directly since it is a pchar }
  1106. jsr _LVOOpenLibrary(a6)
  1107. move.l d0,_UtilityBase
  1108. beq @exitprg
  1109. moveq.l #0,d0
  1110. move.l dosname,a1 { directly since it is a pchar }
  1111. jsr _LVOOpenLibrary(a6)
  1112. move.l d0,_DOSBase
  1113. beq @exitprg
  1114. { Find standard input and output }
  1115. { for CLI }
  1116. @OpenFiles:
  1117. move.l _DOSBase,a6
  1118. jsr _LVOInput(a6) { get standard in }
  1119. move.l d0, StdInputHandle { save standard Input handle }
  1120. { move.l d0,d1 }{ set up for next call }
  1121. { jsr _LVOIsInteractive(a6)}{ is it interactive? }
  1122. { move.l #_Input,a0 }{ get file record again }
  1123. { move.b d0,INTERACTIVE(a0) }{ set flag }
  1124. { beq StdInNotInteractive }{ skip this if not interactive }
  1125. { move.l BUFFER(a0),a1 }{ get buffer address }
  1126. { add.l #1,a1 }{ make end one byte further on }
  1127. { move.l a1,MAX(a0) }{ set buffer size }
  1128. { move.l a1,CURRENT(a0) }{ will need a read }
  1129. bra @OpenStdOutput
  1130. @StdInNotInteractive
  1131. { jsr _p%FillBuffer } { fill the buffer }
  1132. @OpenStdOutput
  1133. jsr _LVOOutput(a6) { get ouput file handle }
  1134. move.l d0,StdOutputHandle { get file record }
  1135. bra @startupend
  1136. { move.l d0,d1 } { set up for call }
  1137. { jsr _LVOIsInteractive(a6) } { is it interactive? }
  1138. { move.l #_Output,a0 } { get file record }
  1139. { move.b d0,INTERACTIVE(a0)} { set flag }
  1140. @exitprg:
  1141. move.l d6,a6 { restore a6 }
  1142. move.l #219,d0
  1143. jsr HALT_ERROR
  1144. @startupend:
  1145. move.l d6,a6 { restore a6 }
  1146. end;
  1147. begin
  1148. errno:= 0;
  1149. { Initial state is on -- in case of RunErrors before the i/o handles are }
  1150. { ok. }
  1151. Initial:=TRUE;
  1152. { Initialize ExitProc }
  1153. ExitProc:=Nil;
  1154. Startup;
  1155. { to test stack depth }
  1156. loweststack:=maxlongint;
  1157. { Setup heap }
  1158. InitHeap;
  1159. { Setup stdin, stdout and stderr }
  1160. OpenStdIO(Input,fmInput,StdInputHandle);
  1161. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1162. { The Amiga does not seem to have a StdError }
  1163. { handle, therefore make the StdError handle }
  1164. { equal to the StdOutputHandle. }
  1165. StdErrorHandle := StdOutputHandle;
  1166. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1167. { Now Handles and function handlers are setup }
  1168. { correctly. }
  1169. Initial:=FALSE;
  1170. { Reset IO Error }
  1171. InOutRes:=0;
  1172. { Startup }
  1173. { Only AmigaOS v2.04 or greater is supported }
  1174. If KickVersion < 36 then
  1175. Begin
  1176. WriteLn('v36 or greater of Kickstart required.');
  1177. Halt(1);
  1178. end;
  1179. argc:=GetParamCount(args);
  1180. OrigDir := 0;
  1181. end.
  1182. {
  1183. $Log$
  1184. Revision 1.6 1998-07-02 12:37:52 carl
  1185. * IOCheck for chdir,rmdir and mkdir as in TP
  1186. Revision 1.5 1998/07/01 14:30:56 carl
  1187. * forgot that includes are case sensitive
  1188. Revision 1.4 1998/07/01 14:13:50 carl
  1189. * do_open bugfix
  1190. * correct conversion of Amiga error codes to TP error codes
  1191. * InoutRes word bugfix
  1192. * parameter counting fixed
  1193. * new stack checking implemented
  1194. + IOCheck for chdir,rmdir,getdir and rmdir
  1195. * do_filepos was wrong
  1196. + chdir correctly implemented
  1197. * getdir correctly implemented
  1198. Revision 1.1.1.1 1998/03/25 11:18:47 root
  1199. * Restored version
  1200. Revision 1.14 1998/03/21 04:20:09 carl
  1201. * correct ExecBase pointer (from Nils Sjoholm)
  1202. * correct OpenLibrary vector (from Nils Sjoholm)
  1203. Revision 1.13 1998/03/14 21:34:32 carl
  1204. * forgot to save a6 in Startup routine
  1205. Revision 1.12 1998/02/24 21:19:42 carl
  1206. *** empty log message ***
  1207. Revision 1.11 1998/02/23 02:22:49 carl
  1208. * bugfix if linking problems
  1209. Revision 1.9 1998/02/06 16:34:32 carl
  1210. + do_open is now standard with other platforms
  1211. Revision 1.8 1998/02/02 15:01:45 carl
  1212. * fixed bug with opening library versions (from Nils Sjoholm)
  1213. Revision 1.7 1998/01/31 19:35:19 carl
  1214. + added opening of utility.library
  1215. Revision 1.6 1998/01/29 23:20:54 peter
  1216. - Removed Backslash convert
  1217. Revision 1.5 1998/01/27 10:55:04 peter
  1218. * Amiga uses / not \, so change AllowSlash -> AllowBackSlash
  1219. Revision 1.4 1998/01/25 21:53:20 peter
  1220. + Universal Handles support for StdIn/StdOut/StdErr
  1221. * Updated layout of sysamiga.pas
  1222. Revision 1.3 1998/01/24 21:09:53 carl
  1223. + added missing input/output function pointers
  1224. Revision 1.2 1998/01/24 14:08:25 carl
  1225. * RunError 217 --> RunError 219 (cannot open lib)
  1226. + Standard Handle names implemented
  1227. Revision 1.1 1998/01/24 05:12:15 carl
  1228. + initial revision, some stuff still missing though.
  1229. (and as you might imagine ... untested :))
  1230. }