sysamiga.pas 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Carl Eric Codere
  5. Some parts taken from
  6. Marcel Timmermans - Modula 2 Compiler
  7. Nils Sjoholm - Amiga porter
  8. Matthew Dillon - Dice C (with his kind permission)
  9. [email protected]
  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 sysamiga;
  17. {--------------------------------------------------------------------}
  18. { LEFT TO DO: }
  19. {--------------------------------------------------------------------}
  20. { o GetDir with different drive numbers }
  21. {--------------------------------------------------------------------}
  22. {$I os.inc}
  23. { AmigaOS uses character #10 as eoln only }
  24. {$DEFINE SHORT_LINEBREAK}
  25. interface
  26. { used for single computations }
  27. const BIAS4 = $7f-1;
  28. {$I systemh.inc}
  29. {$I heaph.inc}
  30. const
  31. UnusedHandle : longint = -1;
  32. StdInputHandle : longint = 0;
  33. StdOutputHandle : longint = 0;
  34. StdErrorHandle : longint = 0;
  35. _ExecBase:longint = $4;
  36. _WorkbenchMsg : longint = 0;
  37. _IntuitionBase : pointer = nil; { intuition library pointer }
  38. _DosBase : pointer = nil; { DOS library pointer }
  39. _UtilityBase : pointer = nil; { utiity library pointer }
  40. { Required for crt unit }
  41. function do_read(h,addr,len : longint) : longint;
  42. function do_write(h,addr,len : longint) : longint;
  43. implementation
  44. const
  45. intuitionname : pchar = 'intuition.library';
  46. dosname : pchar = 'dos.library';
  47. utilityname : pchar = 'utility.library';
  48. argc : longint = 0;
  49. { AmigaOS does not autoamtically deallocate memory on program termination }
  50. { therefore we have to handle this manually. This is a list of allocated }
  51. { pointers from the OS, we cannot use a linked list, because the linked }
  52. { list itself uses the HEAP! }
  53. pointerlist : array[1..8] of longint =
  54. (0,0,0,0,0,0,0,0);
  55. {$I exec.inc}
  56. TYPE
  57. TDateStamp = packed record
  58. ds_Days : Longint; { Number of days since Jan. 1, 1978 }
  59. ds_Minute : Longint; { Number of minutes past midnight }
  60. ds_Tick : Longint; { Number of ticks past minute }
  61. end;
  62. PDateStamp = ^TDateStamp;
  63. PFileInfoBlock = ^TfileInfoBlock;
  64. TFileInfoBlock = packed record
  65. fib_DiskKey : Longint;
  66. fib_DirEntryType : Longint;
  67. { Type of Directory. If < 0, then a plain file.
  68. If > 0 a directory }
  69. fib_FileName : Array [0..107] of Char;
  70. { Null terminated. Max 30 chars used for now }
  71. fib_Protection : Longint;
  72. { bit mask of protection, rwxd are 3-0. }
  73. fib_EntryType : Longint;
  74. fib_Size : Longint; { Number of bytes in file }
  75. fib_NumBlocks : Longint; { Number of blocks in file }
  76. fib_Date : TDateStamp; { Date file last changed }
  77. fib_Comment : Array [0..79] of Char;
  78. { Null terminated comment associated with file }
  79. fib_Reserved : Array [0..35] of Char;
  80. end;
  81. TProcess = packed record
  82. pr_Task : TTask;
  83. pr_MsgPort : TMsgPort; { This is BPTR address from DOS functions }
  84. {126} pr_Pad : Word; { Remaining variables on 4 byte boundaries }
  85. {128} pr_SegList : Pointer; { Array of seg lists used by this process }
  86. {132} pr_StackSize : Longint; { Size of process stack in bytes }
  87. {136} pr_GlobVec : Pointer; { Global vector for this process (BCPL) }
  88. {140} pr_TaskNum : Longint; { CLI task number of zero if not a CLI }
  89. {144} pr_StackBase : BPTR; { Ptr to high memory end of process stack }
  90. {148} pr_Result2 : Longint; { Value of secondary result from last call }
  91. {152} pr_CurrentDir : BPTR; { Lock associated with current directory }
  92. {156} pr_CIS : BPTR; { Current CLI Input Stream }
  93. {160} pr_COS : BPTR; { Current CLI Output Stream }
  94. {164} pr_ConsoleTask : Pointer; { Console handler process for current window}
  95. {168} pr_FileSystemTask : Pointer; { File handler process for current drive }
  96. {172} pr_CLI : BPTR; { pointer to ConsoleLineInterpreter }
  97. pr_ReturnAddr : Pointer; { pointer to previous stack frame }
  98. pr_PktWait : Pointer; { Function to be called when awaiting msg }
  99. pr_WindowPtr : Pointer; { Window for error printing }
  100. { following definitions are new with 2.0 }
  101. pr_HomeDir : BPTR; { Home directory of executing program }
  102. pr_Flags : Longint; { flags telling dos about process }
  103. pr_ExitCode : Pointer; { code to call on exit of program OR NULL }
  104. pr_ExitData : Longint; { Passed as an argument to pr_ExitCode. }
  105. pr_Arguments : PChar; { Arguments passed to the process at start }
  106. pr_LocalVars : TMinList; { Local environment variables }
  107. pr_ShellPrivate : Longint; { for the use of the current shell }
  108. pr_CES : BPTR; { Error stream - IF NULL, use pr_COS }
  109. end;
  110. PProcess = ^TProcess;
  111. { AmigaOS does not automatically close opened files on exit back to }
  112. { the operating system, therefore as a precuation we close all files }
  113. { manually on exit. }
  114. PFileList = ^TFileList;
  115. TFileList = record { no packed, must be correctly aligned }
  116. Handle: longint; { Handle to file }
  117. next: pfilelist; { Next file in list }
  118. closed: boolean; { TRUE=file already closed }
  119. end;
  120. Const
  121. CTRL_C = 20; { Error code on CTRL-C press }
  122. SIGBREAKF_CTRL_C = $1000; { CTRL-C signal flags }
  123. _LVOFindTask = -294;
  124. _LVOWaitPort = -384;
  125. _LVOGetMsg = -372;
  126. _LVOOpenLibrary = -552;
  127. _LVOCloseLibrary = -414;
  128. _LVOClose = -36;
  129. _LVOOpen = -30;
  130. _LVOIoErr = -132;
  131. _LVOSeek = -66;
  132. _LVODeleteFile = -72;
  133. _LVORename = -78;
  134. _LVOWrite = -48;
  135. _LVORead = -42;
  136. _LVOCreateDir = -120;
  137. _LVOSetCurrentDirName = -558;
  138. _LVOGetCurrentDirName = -564;
  139. _LVOInput = -54;
  140. _LVOOutput = -60;
  141. _LVOUnLock = -90;
  142. _LVOLock = -84;
  143. _LVOCurrentDir = -126;
  144. _LVONameFromLock = -402;
  145. _LVONameFromFH = -408;
  146. _LVOGetProgramName = -576;
  147. _LVOGetProgramDir = -600;
  148. _LVODupLock = -96;
  149. _LVOExamine = -102;
  150. _LVOParentDir = -210;
  151. _LVOSetFileSize = -456;
  152. _LVOSetSignal = -306;
  153. _LVOAllocVec = -684;
  154. _LVOFreeVec = -690;
  155. { Errors from IoErr(), etc. }
  156. ERROR_NO_FREE_STORE = 103;
  157. ERROR_TASK_TABLE_FULL = 105;
  158. ERROR_BAD_TEMPLATE = 114;
  159. ERROR_BAD_NUMBER = 115;
  160. ERROR_REQUIRED_ARG_MISSING = 116;
  161. ERROR_KEY_NEEDS_ARG = 117;
  162. ERROR_TOO_MANY_ARGS = 118;
  163. ERROR_UNMATCHED_QUOTES = 119;
  164. ERROR_LINE_TOO_LONG = 120;
  165. ERROR_FILE_NOT_OBJECT = 121;
  166. ERROR_INVALID_RESIDENT_LIBRARY = 122;
  167. ERROR_NO_DEFAULT_DIR = 201;
  168. ERROR_OBJECT_IN_USE = 202;
  169. ERROR_OBJECT_EXISTS = 203;
  170. ERROR_DIR_NOT_FOUND = 204;
  171. ERROR_OBJECT_NOT_FOUND = 205;
  172. ERROR_BAD_STREAM_NAME = 206;
  173. ERROR_OBJECT_TOO_LARGE = 207;
  174. ERROR_ACTION_NOT_KNOWN = 209;
  175. ERROR_INVALID_COMPONENT_NAME = 210;
  176. ERROR_INVALID_LOCK = 211;
  177. ERROR_OBJECT_WRONG_TYPE = 212;
  178. ERROR_DISK_NOT_VALIDATED = 213;
  179. ERROR_DISK_WRITE_PROTECTED = 214;
  180. ERROR_RENAME_ACROSS_DEVICES = 215;
  181. ERROR_DIRECTORY_NOT_EMPTY = 216;
  182. ERROR_TOO_MANY_LEVELS = 217;
  183. ERROR_DEVICE_NOT_MOUNTED = 218;
  184. ERROR_SEEK_ERROR = 219;
  185. ERROR_COMMENT_TOO_BIG = 220;
  186. ERROR_DISK_FULL = 221;
  187. ERROR_DELETE_PROTECTED = 222;
  188. ERROR_WRITE_PROTECTED = 223;
  189. ERROR_READ_PROTECTED = 224;
  190. ERROR_NOT_A_DOS_DISK = 225;
  191. ERROR_NO_DISK = 226;
  192. ERROR_NO_MORE_ENTRIES = 232;
  193. { added for 1.4 }
  194. ERROR_IS_SOFT_LINK = 233;
  195. ERROR_OBJECT_LINKED = 234;
  196. ERROR_BAD_HUNK = 235;
  197. ERROR_NOT_IMPLEMENTED = 236;
  198. ERROR_RECORD_NOT_LOCKED = 240;
  199. ERROR_LOCK_COLLISION = 241;
  200. ERROR_LOCK_TIMEOUT = 242;
  201. ERROR_UNLOCK_ERROR = 243;
  202. var
  203. Initial: boolean; { Have successfully opened Std I/O }
  204. errno : word; { AmigaOS IO Error number }
  205. FileList : pFileList; { Linked list of opened files }
  206. {old_exit: Pointer; not needed anymore }
  207. FromHalt : boolean;
  208. OrigDir : Longint; { Current lock on original startup directory }
  209. {$I system.inc}
  210. {$I lowmath.inc}
  211. { ************************ AMIGAOS STUB ROUTINES ************************* }
  212. procedure DateStamp(var ds : tDateStamp);
  213. begin
  214. asm
  215. MOVE.L A6,-(A7)
  216. MOVE.L ds,d1
  217. { LAST THING TO SETUP SHOULD BE A6, otherwise you can }
  218. { not accept local variable, nor any parameters! :) }
  219. MOVE.L _DOSBase,A6
  220. JSR -192(A6)
  221. MOVE.L (A7)+,A6
  222. end;
  223. end;
  224. { UNLOCK the BPTR pointed to in L }
  225. Procedure Unlock(alock: longint);
  226. Begin
  227. asm
  228. move.l alock,d1
  229. move.l a6,d6 { save base pointer }
  230. move.l _DosBase,a6
  231. jsr _LVOUnlock(a6)
  232. move.l d6,a6 { restore base pointer }
  233. end;
  234. end;
  235. { Change to the directory pointed to in the lock }
  236. Function CurrentDir(alock : longint) : longint;
  237. Begin
  238. asm
  239. move.l alock,d1
  240. move.l a6,d6 { save base pointer }
  241. move.l _DosBase,a6
  242. jsr _LVOCurrentDir(a6)
  243. move.l d6,a6 { restore base pointer }
  244. move.l d0,@Result
  245. end;
  246. end;
  247. { Duplicate a lock }
  248. Function DupLock(alock: longint): Longint;
  249. Begin
  250. asm
  251. move.l alock,d1
  252. move.l a6,d6 { save base pointer }
  253. move.l _DosBase,a6
  254. jsr _LVODupLock(a6)
  255. move.l d6,a6 { restore base pointer }
  256. move.l d0,@Result
  257. end;
  258. end;
  259. { Returns a lock on the directory was loaded from }
  260. Function GetProgramLock: longint;
  261. Begin
  262. asm
  263. move.l a6,d6 { save base pointer }
  264. move.l _DosBase,a6
  265. jsr _LVOGetProgramDir(a6)
  266. move.l d6,a6 { restore base pointer }
  267. move.l d0,@Result
  268. end;
  269. end;
  270. Function Examine(alock :longint; var fib: TFileInfoBlock) : Boolean;
  271. Begin
  272. asm
  273. move.l d2,-(sp)
  274. move.l fib,d2 { pointer to FIB }
  275. move.l alock,d1
  276. move.l a6,d6 { save base pointer }
  277. move.l _DosBase,a6
  278. jsr _LVOExamine(a6)
  279. move.l d6,a6 { restore base pointer }
  280. tst.l d0
  281. bne @success
  282. bra @end
  283. @success:
  284. move.b #1,d0
  285. @end:
  286. move.b d0,@Result
  287. move.l (sp)+,d2
  288. end;
  289. end;
  290. { Returns the parent directory of a lock }
  291. Function ParentDir(alock : longint): longint;
  292. Begin
  293. asm
  294. move.l alock,d1
  295. move.l a6,d6 { save base pointer }
  296. move.l _DosBase,a6
  297. jsr _LVOParentDir(a6)
  298. move.l d6,a6 { restore base pointer }
  299. move.l d0,@Result
  300. end;
  301. end;
  302. Function FindTask(p : PChar): PProcess;
  303. Begin
  304. asm
  305. move.l a6,d6 { Save base pointer }
  306. move.l p,d0
  307. move.l d0,a1
  308. move.l _ExecBase,a6
  309. jsr _LVOFindTask(a6)
  310. move.l d6,a6 { Restore base pointer }
  311. move.l d0,@Result
  312. end;
  313. end;
  314. {$S-}
  315. Procedure stack_check; assembler;
  316. { Check for local variable allocation }
  317. { On Entry -> d0 : size of local stack we are trying to allocate }
  318. asm
  319. XDEF STACKCHECK
  320. move.l sp,d1 { get value of stack pointer }
  321. { We must add some security, because Writing the RunError strings }
  322. { requires a LOT of stack space (at least 1030 bytes!) }
  323. add.l #2048,d0
  324. sub.l d0,d1 { sp - stack_size }
  325. move.l _ExecBase,a0
  326. move.l 276(A0),A0 { ExecBase.thisTask }
  327. { if allocated stack_pointer - splower <= 0 then stack_ovf }
  328. cmp.l 58(A0),D1 { Task.SpLower }
  329. bgt @Ok
  330. move.l #202,d0
  331. jsr HALT_ERROR { stack overflow }
  332. @Ok:
  333. end;
  334. { This routine from EXEC determines if the Ctrl-C key has }
  335. { been used since the last call to I/O routines. }
  336. { Use to halt the program. }
  337. { Returns the state of the old signals. }
  338. Function SetSignal(newSignal: longint; SignalMask: longint): longint;
  339. Begin
  340. asm
  341. move.l newSignal,d0
  342. move.l SignalMask,d1
  343. move.l a6,d6 { save Base pointer into scratch register }
  344. move.l _ExecBase,a6
  345. jsr _LVOSetSignal(a6)
  346. move.l d6,a6
  347. move.l d0,@Result
  348. end;
  349. end;
  350. Function AllocVec(bytesize: longint; attributes: longint):longint;
  351. Begin
  352. asm
  353. move.l bytesize,d0
  354. move.l attributes,d1
  355. move.l a6,d6 { save Base pointer into scratch register }
  356. move.l _ExecBase,a6
  357. jsr _LVOAllocVec(a6)
  358. move.l d6,a6
  359. move.l d0,@Result
  360. end;
  361. end;
  362. Procedure FreeVec(p: longint);
  363. Begin
  364. asm
  365. move.l p,a1
  366. move.l a6,d6 { save Base pointer into scratch register }
  367. move.l _ExecBase,a6
  368. jsr _LVOFreeVec(a6)
  369. move.l d6,a6
  370. end;
  371. end;
  372. { Converts an AMIGAOS error code to a TP compatible error code }
  373. Procedure Error2InOut;
  374. Begin
  375. case errno of
  376. ERROR_BAD_NUMBER,
  377. ERROR_ACTION_NOT_KNOWN,
  378. ERROR_NOT_IMPLEMENTED : InOutRes := 1;
  379. ERROR_OBJECT_NOT_FOUND : InOutRes := 2;
  380. ERROR_DIR_NOT_FOUND : InOutRes := 3;
  381. ERROR_DISK_WRITE_PROTECTED : InOutRes := 150;
  382. ERROR_OBJECT_WRONG_TYPE : InOutRes := 151;
  383. ERROR_OBJECT_EXISTS,
  384. ERROR_DELETE_PROTECTED,
  385. ERROR_WRITE_PROTECTED,
  386. ERROR_READ_PROTECTED,
  387. ERROR_OBJECT_IN_USE,
  388. ERROR_DIRECTORY_NOT_EMPTY : InOutRes := 5;
  389. ERROR_NO_MORE_ENTRIES : InOutRes := 18;
  390. ERROR_RENAME_ACROSS_DEVICES : InOutRes := 17;
  391. ERROR_DISK_FULL : InOutRes := 101;
  392. ERROR_INVALID_RESIDENT_LIBRARY : InoutRes := 153;
  393. ERROR_BAD_HUNK : InOutRes := 153;
  394. ERROR_NOT_A_DOS_DISK : InOutRes := 157;
  395. ERROR_NO_DISK,
  396. ERROR_DISK_NOT_VALIDATED,
  397. ERROR_DEVICE_NOT_MOUNTED : InOutRes := 152;
  398. ERROR_SEEK_ERROR : InOutRes := 156;
  399. ERROR_LOCK_COLLISION,
  400. ERROR_LOCK_TIMEOUT,
  401. ERROR_UNLOCK_ERROR,
  402. ERROR_INVALID_LOCK,
  403. ERROR_INVALID_COMPONENT_NAME,
  404. ERROR_BAD_STREAM_NAME,
  405. ERROR_FILE_NOT_OBJECT : InOutRes := 6;
  406. else
  407. InOutres := errno;
  408. end;
  409. errno:=0;
  410. end;
  411. procedure CloseLibrary(lib : pointer);
  412. { Close the library pointed to in lib }
  413. Begin
  414. asm
  415. MOVE.L A6,-(A7)
  416. MOVE.L lib,a1
  417. MOVE.L _ExecBase,A6
  418. JSR _LVOCloseLibrary(A6)
  419. MOVE.L (A7)+,A6
  420. end;
  421. end;
  422. Function KickVersion: word; assembler;
  423. asm
  424. move.l _ExecBase, a0 { Get Exec Base }
  425. move.w 20(a0), d0 { Return version - version at this offset }
  426. end;
  427. { ************************ AMIGAOS SUPP ROUTINES ************************* }
  428. (* Procedure CloseList(p: pFileList);*)
  429. (***********************************************************************)
  430. (* PROCEDURE CloseList *)
  431. (* Description: This routine each time the program is about to *)
  432. (* terminate, it closes all opened file handles, as this is not *)
  433. (* handled by the operating system. *)
  434. (* p -> Start of linked list of opened files *)
  435. (***********************************************************************)
  436. (* var
  437. hp: pFileList;
  438. hp1: pFileList;
  439. h: longint;
  440. Begin
  441. hp:=p;
  442. while Assigned(hp) do
  443. Begin
  444. if NOT hp^.closed then
  445. Begin
  446. h:=hp^.handle;
  447. if (h <> StdInputHandle) and (h <> StdOutputHandle) and (h <> StdErrorHandle) then
  448. Begin
  449. { directly close file here, it is faster then doing }
  450. { it do_close. }
  451. asm
  452. move.l h,d1
  453. move.l a6,d6 { save a6 }
  454. move.l _DOSBase,a6
  455. jsr _LVOClose(a6)
  456. move.l d6,a6 { restore a6 }
  457. end;
  458. end;
  459. end;
  460. hp1:=hp;
  461. hp:=hp^.next;
  462. dispose(hp1);
  463. end;
  464. end;*)
  465. (* Procedure AddToList(var p: pFileList; h: longint);*)
  466. (***********************************************************************)
  467. (* PROCEDURE AddToList *)
  468. (* Description: Adds a node to the linked list of files. *)
  469. (* *)
  470. (* p -> Start of File list linked list, if not allocated allocates *)
  471. (* it for you. *)
  472. (* h -> handle of file to add *)
  473. (***********************************************************************)
  474. (* var
  475. hp: pFileList;
  476. hp1: pFileList;
  477. Begin
  478. if p = nil then
  479. Begin
  480. new(p);
  481. p^.handle:=h;
  482. p^.closed := FALSE;
  483. p^.next := nil;
  484. exit;
  485. end;
  486. hp:=p;
  487. { Find last list in entry }
  488. while assigned(hp) do
  489. Begin
  490. if hp^.next = nil then break;
  491. hp:=hp^.next;
  492. end;
  493. { Found last list in entry then add it to the list }
  494. new(hp1);
  495. hp^.next:=hp1;
  496. hp1^.next:=nil;
  497. hp1^.handle:=h;
  498. hp1^.closed:=FALSE;
  499. end;
  500. Procedure SetClosedList(var p: pFileList; h: longint);
  501. { Set the file flag to closed if the file is being closed }
  502. var
  503. hp: pFileList;
  504. Begin
  505. hp:=p;
  506. while assigned(hp) do
  507. Begin
  508. if hp^.handle = h then
  509. Begin
  510. hp^.closed:=TRUE;
  511. break;
  512. end;
  513. hp:=hp^.next;
  514. end;
  515. end;*)
  516. {*****************************************************************************
  517. System Dependent Exit code
  518. *****************************************************************************}
  519. Procedure system_exit;
  520. var
  521. i: byte;
  522. Begin
  523. { We must remove the CTRL-C FALG here because halt }
  524. { may call I/O routines, which in turn might call }
  525. { halt, so a recursive stack crash }
  526. IF (SetSignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 THEN
  527. SetSignal(0,SIGBREAKF_CTRL_C);
  528. { Close remaining opened files }
  529. { CloseList(FileList); }
  530. if (OrigDir <> 0) then
  531. Begin
  532. Unlock(CurrentDir(OrigDir));
  533. OrigDir := 0;
  534. end;
  535. { Is this a normal exit - YES, close libs }
  536. IF NOT FromHalt then
  537. Begin
  538. { close the libraries }
  539. If _UtilityBase <> nil then
  540. CloseLibrary(_UtilityBase);
  541. If _DosBase <> nil then
  542. CloseLibrary(_DosBase);
  543. If _IntuitionBase <> nil then
  544. CloseLibrary(_IntuitionBase);
  545. _UtilityBase := nil;
  546. _DosBase := nil;
  547. _IntuitionBase := nil;
  548. end;
  549. { Dispose of extraneous allocated pointers }
  550. for I:=1 to 8 do
  551. Begin
  552. if pointerlist[i] <> 0 then FreeVec(pointerlist[i]);
  553. end;
  554. { exitproc:=old_exit;obsolete }
  555. end;
  556. procedure halt(errnum : byte);
  557. begin
  558. { Indicate to the SYSTEM EXIT procedure that we are calling it }
  559. { from halt, and that its library will be closed HERE and not }
  560. { in the exit procedure. }
  561. FromHalt:=TRUE;
  562. { We must remove the CTRL-C FALG here because halt }
  563. { may call I/O routines, which in turn might call }
  564. { halt, so a recursive stack crash }
  565. IF (SetSignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 THEN
  566. SetSignal(0,SIGBREAKF_CTRL_C);
  567. { WE can only FLUSH the stdio }
  568. { if the handles have correctly }
  569. { been set. }
  570. { No exit procedures exist }
  571. { if in initial state }
  572. If NOT Initial then
  573. Begin
  574. do_exit;
  575. flush(stderr);
  576. end;
  577. { close the libraries }
  578. If _UtilityBase <> nil then
  579. CloseLibrary(_UtilityBase);
  580. If _DosBase <> nil then
  581. CloseLibrary(_DosBase);
  582. If _IntuitionBase <> nil then
  583. CloseLibrary(_IntuitionBase);
  584. _UtilityBase := nil;
  585. _DosBase := nil;
  586. _IntuitionBase := nil;
  587. asm
  588. clr.l d0
  589. move.b errnum,d0
  590. move.l STKPTR,sp
  591. rts
  592. end;
  593. end;
  594. { ************************ PARAMCOUNT/PARAMSTR *************************** }
  595. function paramcount : longint;
  596. Begin
  597. paramcount := argc;
  598. end;
  599. function args : pointer; assembler;
  600. asm
  601. move.l __ARGS,d0
  602. end;
  603. Function GetParamCount(const p: pchar): longint;
  604. var
  605. i: word;
  606. count: word;
  607. Begin
  608. i:=0;
  609. count:=0;
  610. while p[count] <> #0 do
  611. Begin
  612. if (p[count] <> ' ') and (p[count] <> #9) and (p[count] <> #0) then
  613. Begin
  614. i:=i+1;
  615. while (p[count] <> ' ') and (p[count] <> #9) and (p[count] <> #0) do
  616. count:=count+1;
  617. end;
  618. if p[count] = #0 then break;
  619. count:=count+1;
  620. end;
  621. GetParamCount:=longint(i);
  622. end;
  623. Function GetParam(index: word; const p : pchar): string;
  624. { On Entry: index = string index to correct parameter }
  625. { On exit: = correct character index into pchar array }
  626. { Returns correct index to command line argument }
  627. var
  628. count: word;
  629. localindex: word;
  630. l: byte;
  631. temp: string;
  632. Begin
  633. temp:='';
  634. count := 0;
  635. { first index is one }
  636. localindex := 1;
  637. l:=0;
  638. While p[count] <> #0 do
  639. Begin
  640. if (p[count] <> ' ') and (p[count] <> #9) then
  641. Begin
  642. if localindex = index then
  643. Begin
  644. while (p[count] <> #0) and (p[count] <> ' ') and (p[count] <> #9) and (l < 256) do
  645. Begin
  646. temp:=temp+p[count];
  647. l:=l+1;
  648. count:=count+1;
  649. end;
  650. temp[0]:=char(l);
  651. GetParam:=temp;
  652. exit;
  653. end;
  654. { Point to next argument in list }
  655. while (p[count] <> #0) and (p[count] <> ' ') and (p[count] <> #9) do
  656. Begin
  657. count:=count+1;
  658. end;
  659. localindex:=localindex+1;
  660. end;
  661. if p[count] = #0 then break;
  662. count:=count+1;
  663. end;
  664. GetParam:=temp;
  665. end;
  666. Function GetProgramDir : String;
  667. var
  668. s1: string;
  669. alock: longint;
  670. counter : byte;
  671. Begin
  672. FillChar(@s1,255,#0);
  673. { GetLock of program directory }
  674. asm
  675. move.l a6,d6 { save a6 }
  676. move.l _DOSBase,a6
  677. jsr _LVOGetProgramDir(a6)
  678. move.l d6,a6 { restore a6 }
  679. move.l d0,alock { save the lock }
  680. end;
  681. if alock <> 0 then
  682. Begin
  683. { Get the name from the lock! }
  684. asm
  685. movem.l d2/d3,-(sp) { save used registers }
  686. move.l alock,d1
  687. lea s1,a0 { Get pointer to string! }
  688. move.l a0,d2
  689. add.l #1,d2 { let us point past the length byte! }
  690. move.l #255,d3
  691. move.l a6,d6 { save a6 }
  692. move.l _DOSBase,a6
  693. jsr _LVONameFromLock(a6)
  694. move.l d6,a6 { restore a6 }
  695. movem.l (sp)+,d2/d3
  696. end;
  697. { no check out the length of the string }
  698. counter := 1;
  699. while s1[counter] <> #0 do
  700. Inc(counter);
  701. s1[0] := char(counter-1);
  702. GetProgramDir := s1;
  703. end
  704. else
  705. GetProgramDir := '';
  706. end;
  707. Function GetProgramName : string;
  708. { Returns ONLY the program name }
  709. { There seems to be a bug in v39 since if the program is not }
  710. { called from its home directory the program name will also }
  711. { contain the path! }
  712. var
  713. s1: string;
  714. counter : byte;
  715. Begin
  716. FillChar(@s1,255,#0);
  717. asm
  718. move.l d2,-(sp) { Save used register }
  719. lea s1,a0 { Get pointer to string! }
  720. move.l a0,d1
  721. add.l #1,d1 { point to correct offset }
  722. move.l #255,d2
  723. move.l a6,d6 { save a6 }
  724. move.l _DOSBase,a6
  725. jsr _LVOGetProgramName(a6)
  726. move.l d6,a6 { restore a6 }
  727. move.l (sp)+,d2 { restore saved register }
  728. end;
  729. { no check out and assign the length of the string }
  730. counter := 1;
  731. while s1[counter] <> #0 do
  732. Inc(counter);
  733. s1[0] := char(counter-1);
  734. { now remove any component path which should not be there }
  735. for counter:=length(s1) downto 1 do
  736. if (s1[counter] = '/') or (s1[counter] = ':') then break;
  737. { readjust counterv to point to character }
  738. if counter <> 1 then
  739. Inc(counter);
  740. GetProgramName:=copy(s1,counter,length(s1));
  741. end;
  742. function paramstr(l : longint) : string;
  743. var
  744. p : pchar;
  745. s1 : string;
  746. begin
  747. { -> Call AmigaOS GetProgramName }
  748. if l = 0 then
  749. Begin
  750. s1 := GetProgramDir;
  751. { If this is a root, then simply don't add '/' }
  752. if s1[length(s1)] = ':' then
  753. paramstr:=s1+GetProgramName
  754. else
  755. { add backslash directory }
  756. paramstr:=s1+'/'+GetProgramName
  757. end
  758. else
  759. if (l>0) and (l<=paramcount) then
  760. begin
  761. p:=args;
  762. paramstr:=GetParam(word(l),p);
  763. end
  764. else paramstr:='';
  765. end;
  766. { ************************************************************************ }
  767. procedure randomize;
  768. var
  769. hl : longint;
  770. time : TDateStamp;
  771. begin
  772. DateStamp(time);
  773. randseed:=time.ds_tick;
  774. end;
  775. function getheapstart:pointer;assembler;
  776. asm
  777. lea.l HEAP,a0
  778. move.l a0,d0
  779. end;
  780. function getheapsize:longint;assembler;
  781. asm
  782. move.l HEAP_SIZE,d0
  783. end ['D0'];
  784. { This routine is used to grow the heap. }
  785. { But here we do a trick, we say that the }
  786. { heap cannot be regrown! }
  787. function sbrk( size: longint): longint;
  788. var
  789. { on exit -1 = if fails. }
  790. p: longint;
  791. i: byte;
  792. Begin
  793. p:=0;
  794. { Is the pointer list full }
  795. if pointerlist[8] <> 0 then
  796. begin
  797. { yes, then don't allocate and simply exit }
  798. sbrk:=-1;
  799. exit;
  800. end;
  801. { Allocate best available memory }
  802. p:=AllocVec(size,0);
  803. if p = 0 then
  804. sbrk:=-1
  805. else
  806. Begin
  807. i:=1;
  808. { add it to the list of allocated pointers }
  809. { first find the last pointer in the list }
  810. while (i < 8) and (pointerlist[i] <> 0) do
  811. i:=i+1;
  812. pointerlist[i]:=p;
  813. sbrk:=p;
  814. end;
  815. end;
  816. {$I heap.inc}
  817. {****************************************************************************
  818. Low Level File Routines
  819. ****************************************************************************}
  820. procedure do_close(h : longint);
  821. { We cannot check for CTRL-C because this routine will be called }
  822. { on HALT to close all remaining opened files. Therefore no }
  823. { CTRL-C checking otherwise a recursive call might result! }
  824. {$ifdef debug}
  825. var
  826. buffer: array[0..255] of char;
  827. {$endif}
  828. begin
  829. { check if the file handle is in the list }
  830. { if so the put its field to closed }
  831. { SetClosedList(FileList,h);}
  832. {$ifdef debug}
  833. asm
  834. move.l h,d1
  835. move.l a6,d6
  836. move.l d2,-(sp)
  837. move.l d3,-(sp)
  838. lea buffer,a0
  839. move.l a0,d2
  840. move.l #255,d3
  841. move.l _DosBase,a6
  842. jsr _LVONameFromFH(a6)
  843. move.l d6,a6
  844. move.l (sp)+,d3
  845. move.l (sp)+,d2
  846. end;
  847. WriteLn(Buffer);
  848. {$endif debug}
  849. asm
  850. move.l h,d1
  851. move.l a6,d6 { save a6 }
  852. move.l _DOSBase,a6
  853. jsr _LVOClose(a6)
  854. move.l d6,a6 { restore a6 }
  855. end;
  856. end;
  857. function do_isdevice(handle:longint):boolean;
  858. begin
  859. if (handle=stdoutputhandle) or (handle=stdinputhandle) or
  860. (handle=stderrorhandle) then
  861. do_isdevice:=TRUE
  862. else
  863. do_isdevice:=FALSE;
  864. end;
  865. procedure do_erase(p : pchar);
  866. begin
  867. if (Setsignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 then
  868. Begin
  869. SetSignal(0,SIGBREAKF_CTRL_C);
  870. Halt(CTRL_C);
  871. end;
  872. asm
  873. move.l a6,d6 { save a6 }
  874. move.l p,d1
  875. move.l _DOSBase,a6
  876. jsr _LVODeleteFile(a6)
  877. tst.l d0 { zero = failure }
  878. bne @noerror
  879. jsr _LVOIoErr(a6)
  880. move.w d0,errno
  881. @noerror:
  882. move.l d6,a6 { restore a6 }
  883. end;
  884. if errno <> 0 then
  885. Error2InOut;
  886. end;
  887. procedure do_rename(p1,p2 : pchar);
  888. begin
  889. if (Setsignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 then
  890. Begin
  891. SetSignal(0,SIGBREAKF_CTRL_C);
  892. Halt(CTRL_C);
  893. end;
  894. asm
  895. move.l a6,d6 { save a6 }
  896. move.l d2,-(sp) { save d2 }
  897. move.l p1,d1
  898. move.l p2,d2
  899. move.l _DOSBase,a6
  900. jsr _LVORename(a6)
  901. move.l (sp)+,d2 { restore d2 }
  902. tst.l d0
  903. bne @dosreend { if zero = error }
  904. jsr _LVOIoErr(a6)
  905. move.w d0,errno
  906. @dosreend:
  907. move.l d6,a6 { restore a6 }
  908. end;
  909. if errno <> 0 then
  910. Error2InOut;
  911. end;
  912. function do_write(h,addr,len : longint) : longint;
  913. begin
  914. if (Setsignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 then
  915. Begin
  916. SetSignal(0,SIGBREAKF_CTRL_C);
  917. Halt(CTRL_C);
  918. end;
  919. if len <= 0 then
  920. Begin
  921. do_write:=0;
  922. exit;
  923. end;
  924. asm
  925. move.l a6,d6
  926. movem.l d2/d3,-(sp)
  927. move.l h,d1 { we must of course set up the }
  928. move.l addr,d2 { parameters BEFORE getting }
  929. move.l len,d3 { _DOSBase }
  930. move.l _DOSBase,a6
  931. jsr _LVOWrite(a6)
  932. movem.l (sp)+,d2/d3
  933. cmp.l #-1,d0
  934. bne @doswrend { if -1 = error }
  935. jsr _LVOIoErr(a6)
  936. move.w d0,errno
  937. bra @doswrend2
  938. @doswrend:
  939. { we must restore the base pointer before setting the result }
  940. move.l d6,a6
  941. move.l d0,@RESULT
  942. bra @end
  943. @doswrend2:
  944. move.l d6,a6
  945. @end:
  946. end;
  947. If errno <> 0 then
  948. Error2InOut;
  949. end;
  950. function do_read(h,addr,len : longint) : longint;
  951. begin
  952. if (Setsignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 then
  953. Begin
  954. SetSignal(0,SIGBREAKF_CTRL_C);
  955. Halt(CTRL_C);
  956. end;
  957. if len <= 0 then
  958. Begin
  959. do_read:=0;
  960. exit;
  961. end;
  962. asm
  963. move.l a6,d6
  964. movem.l d2/d3,-(sp)
  965. move.l h,d1 { we must set up aparamters BEFORE }
  966. move.l addr,d2 { setting up a6 for the OS call }
  967. move.l len,d3
  968. move.l _DOSBase,a6
  969. jsr _LVORead(a6)
  970. movem.l (sp)+,d2/d3
  971. cmp.l #-1,d0
  972. bne @doswrend { if -1 = error }
  973. jsr _LVOIoErr(a6)
  974. move.w d0,errno
  975. bra @doswrend2
  976. @doswrend:
  977. { to store a result for the function }
  978. { we must of course first get back the}
  979. { base pointer! }
  980. move.l d6,a6
  981. move.l d0,@RESULT
  982. bra @end
  983. @doswrend2:
  984. move.l d6,a6
  985. @end:
  986. end;
  987. If errno <> 0 then
  988. Error2InOut;
  989. end;
  990. function do_filepos(handle : longint) : longint;
  991. begin
  992. if (Setsignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 then
  993. Begin
  994. { Clear CTRL-C signal }
  995. SetSignal(0,SIGBREAKF_CTRL_C);
  996. Halt(CTRL_C);
  997. end;
  998. asm
  999. move.l a6,d6
  1000. move.l handle,d1
  1001. move.l d2,-(sp)
  1002. move.l d3,-(sp) { save registers }
  1003. clr.l d2 { offset 0 }
  1004. move.l #0,d3 { OFFSET_CURRENT }
  1005. move.l _DOSBase,a6
  1006. jsr _LVOSeek(a6)
  1007. move.l (sp)+,d3 { restore registers }
  1008. move.l (sp)+,d2
  1009. cmp.l #-1,d0 { is there a file access error? }
  1010. bne @noerr
  1011. jsr _LVOIoErr(a6)
  1012. move.w d0,errno
  1013. bra @fposend
  1014. @noerr:
  1015. move.l d6,a6 { restore a6 }
  1016. move.l d0,@Result
  1017. bra @end
  1018. @fposend:
  1019. move.l d6,a6 { restore a6 }
  1020. @end:
  1021. end;
  1022. If errno <> 0 then
  1023. Error2InOut;
  1024. end;
  1025. procedure do_seek(handle,pos : longint);
  1026. begin
  1027. if (Setsignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 then
  1028. Begin
  1029. { Clear CTRL-C signal }
  1030. SetSignal(0,SIGBREAKF_CTRL_C);
  1031. Halt(CTRL_C);
  1032. end;
  1033. asm
  1034. move.l a6,d6
  1035. move.l handle,d1
  1036. move.l d2,-(sp)
  1037. move.l d3,-(sp) { save registers }
  1038. move.l pos,d2
  1039. { -1 }
  1040. move.l #$ffffffff,d3 { OFFSET_BEGINNING }
  1041. move.l _DOSBase,a6
  1042. jsr _LVOSeek(a6)
  1043. move.l (sp)+,d3 { restore registers }
  1044. move.l (sp)+,d2
  1045. cmp.l #-1,d0 { is there a file access error? }
  1046. bne @noerr
  1047. jsr _LVOIoErr(a6)
  1048. move.w d0,errno
  1049. bra @seekend
  1050. @noerr:
  1051. @seekend:
  1052. move.l d6,a6 { restore a6 }
  1053. end;
  1054. If errno <> 0 then
  1055. Error2InOut;
  1056. end;
  1057. function do_seekend(handle:longint):longint;
  1058. begin
  1059. if (Setsignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 then
  1060. Begin
  1061. { Clear CTRL-C signal }
  1062. SetSignal(0,SIGBREAKF_CTRL_C);
  1063. Halt(CTRL_C);
  1064. end;
  1065. asm
  1066. { seek from end of file }
  1067. move.l a6,d6
  1068. move.l handle,d1
  1069. move.l d2,-(sp)
  1070. move.l d3,-(sp) { save registers }
  1071. clr.l d2
  1072. move.l #1,d3 { OFFSET_END }
  1073. move.l _DOSBase,a6
  1074. jsr _LVOSeek(a6)
  1075. move.l (sp)+,d3 { restore registers }
  1076. move.l (sp)+,d2
  1077. cmp.l #-1,d0 { is there a file access error? }
  1078. bne @noerr
  1079. jsr _LVOIoErr(a6)
  1080. move.w d0,errno
  1081. bra @seekend
  1082. @noerr:
  1083. move.l d6,a6 { restore a6 }
  1084. move.l d0,@Result
  1085. bra @end
  1086. @seekend:
  1087. move.l d6,a6 { restore a6 }
  1088. @end:
  1089. end;
  1090. If Errno <> 0 then
  1091. Error2InOut;
  1092. end;
  1093. function do_filesize(handle : longint) : longint;
  1094. var
  1095. aktfilepos : longint;
  1096. begin
  1097. if (Setsignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 then
  1098. Begin
  1099. { Clear CTRL-C signal }
  1100. SetSignal(0,SIGBREAKF_CTRL_C);
  1101. Halt(CTRL_C);
  1102. end;
  1103. aktfilepos:=do_filepos(handle);
  1104. { We have to do this two times, because seek returns the }
  1105. { OLD position }
  1106. do_filesize:=do_seekend(handle);
  1107. do_filesize:=do_seekend(handle);
  1108. do_seek(handle,aktfilepos);
  1109. end;
  1110. procedure do_truncate (handle,pos:longint);
  1111. begin
  1112. { Point to the end of the file }
  1113. { with the new size }
  1114. asm
  1115. @noerr_one: { Seek a second time }
  1116. move.l a6,d6 { Save base pointer }
  1117. move.l handle,d1
  1118. move.l d2,-(sp)
  1119. move.l d3,-(sp) { save registers }
  1120. move.l pos,d2
  1121. move.l #-1,d3 { Setup correct move type }
  1122. move.l _DOSBase,a6 { from beginning of file }
  1123. jsr _LVOSetFileSize(a6)
  1124. move.l (sp)+,d3 { restore registers }
  1125. move.l (sp)+,d2
  1126. cmp.l #-1,d0 { is there a file access error? }
  1127. bne @noerr
  1128. jsr _LVOIoErr(a6)
  1129. move.w d0,errno { Global variable, so no need }
  1130. @noerr: { to restore base pointer now }
  1131. move.l d6,a6 { Restore base pointer }
  1132. end;
  1133. If Errno <> 0 then
  1134. Error2InOut;
  1135. end;
  1136. procedure do_open(var f;p:pchar;flags:longint);
  1137. {
  1138. filerec and textrec have both handle and mode as the first items so
  1139. they could use the same routine for opening/creating.
  1140. when (flags and $100) the file will be append
  1141. when (flags and $1000) the file will be truncate/rewritten
  1142. when (flags and $10000) there is no check for close (needed for textfiles)
  1143. }
  1144. var
  1145. i,j : longint;
  1146. oflags: longint;
  1147. path : string;
  1148. buffer : array[0..255] of char;
  1149. index : integer;
  1150. s : string;
  1151. begin
  1152. path:=strpas(p);
  1153. for index:=1 to length(path) do
  1154. if path[index]='\' then path[index]:='/';
  1155. { remove any dot characters and replace by their current }
  1156. { directory equivalent. }
  1157. if pos('../',path) = 1 then
  1158. { look for parent directory }
  1159. Begin
  1160. delete(path,1,3);
  1161. getdir(0,s);
  1162. j:=length(s);
  1163. while (s[j] <> '/') AND (s[j] <> ':') AND (j > 0 ) do
  1164. dec(j);
  1165. if j > 0 then
  1166. s:=copy(s,1,j);
  1167. path:=s+path;
  1168. end
  1169. else
  1170. if pos('./',path) = 1 then
  1171. { look for current directory }
  1172. Begin
  1173. delete(path,1,2);
  1174. getdir(0,s);
  1175. if (s[length(s)] <> '/') and (s[length(s)] <> ':') then
  1176. s:=s+'/';
  1177. path:=s+path;
  1178. end;
  1179. move(path[1],buffer,length(path));
  1180. buffer[length(path)]:=#0;
  1181. { close first if opened }
  1182. if ((flags and $10000)=0) then
  1183. begin
  1184. case filerec(f).mode of
  1185. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  1186. fmclosed : ;
  1187. else
  1188. begin
  1189. inoutres:=102; {not assigned}
  1190. exit;
  1191. end;
  1192. end;
  1193. end;
  1194. { reset file handle }
  1195. filerec(f).handle:=UnusedHandle;
  1196. { convert filemode to filerec modes }
  1197. { READ/WRITE on existing file }
  1198. { RESET/APPEND }
  1199. oflags := 1005;
  1200. case (flags and 3) of
  1201. 0 : begin
  1202. filerec(f).mode:=fminput;
  1203. end;
  1204. 1 : filerec(f).mode:=fmoutput;
  1205. 2 : filerec(f).mode:=fminout;
  1206. end;
  1207. { READ/WRITE mode, create file in all cases }
  1208. { REWRITE }
  1209. if (flags and $1000)<>0 then
  1210. begin
  1211. filerec(f).mode:=fmoutput;
  1212. oflags := 1006;
  1213. end
  1214. else
  1215. { READ/WRITE mode on existing file }
  1216. { APPEND }
  1217. if (flags and $100)<>0 then
  1218. begin
  1219. filerec(f).mode:=fmoutput;
  1220. oflags := 1005;
  1221. end;
  1222. { empty name is special }
  1223. if p[0]=#0 then
  1224. begin
  1225. case filerec(f).mode of
  1226. fminput : filerec(f).handle:=StdInputHandle;
  1227. fmappend,
  1228. fmoutput : begin
  1229. filerec(f).handle:=StdOutputHandle;
  1230. filerec(f).mode:=fmoutput; {fool fmappend}
  1231. end;
  1232. end;
  1233. exit;
  1234. end;
  1235. asm
  1236. move.l a6,d6 { save a6 }
  1237. move.l d2,-(sp)
  1238. lea buffer,a0
  1239. move.l a0,d1
  1240. move.l oflags,d2 { MODE_READWRITE }
  1241. move.l _DOSBase,a6
  1242. jsr _LVOOpen(a6)
  1243. tst.l d0
  1244. bne @noopenerror { on zero an error occured }
  1245. jsr _LVOIoErr(a6)
  1246. move.w d0,errno
  1247. bra @openend
  1248. @noopenerror:
  1249. move.l (sp)+,d2
  1250. move.l d6,a6 { restore a6 }
  1251. move.l d0,i { we need the base pointer to access this variable }
  1252. bra @end
  1253. @openend:
  1254. move.l d6,a6 { restore a6 }
  1255. move.l (sp)+,d2
  1256. @end:
  1257. end;
  1258. (* if Errno = 0 then*)
  1259. { No error, add file handle to linked list }
  1260. { this must be checked before the call to }
  1261. { Error2InIOut since it resets Errno to 0 }
  1262. (* AddToList(FileList,i);*)
  1263. If Errno <> 0 then
  1264. Error2InOut;
  1265. filerec(f).handle:=i;
  1266. if (flags and $100)<>0 then
  1267. do_seekend(filerec(f).handle);
  1268. end;
  1269. {*****************************************************************************
  1270. UnTyped File Handling
  1271. *****************************************************************************}
  1272. {$i file.inc}
  1273. {*****************************************************************************
  1274. Typed File Handling
  1275. *****************************************************************************}
  1276. {$i typefile.inc}
  1277. {*****************************************************************************
  1278. Text File Handling
  1279. *****************************************************************************}
  1280. {$i text.inc}
  1281. {*****************************************************************************
  1282. Directory Handling
  1283. *****************************************************************************}
  1284. procedure mkdir(const s : string);[IOCheck];
  1285. var
  1286. buffer : array[0..255] of char;
  1287. j: Integer;
  1288. temp : string;
  1289. begin
  1290. { We must check the Ctrl-C before IOChecking of course! }
  1291. if (Setsignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 then
  1292. Begin
  1293. { Clear CTRL-C signal }
  1294. SetSignal(0,SIGBREAKF_CTRL_C);
  1295. Halt(CTRL_C);
  1296. end;
  1297. If InOutRes <> 0 then exit;
  1298. temp:=s;
  1299. for j:=1 to length(temp) do
  1300. if temp[j] = '\' then temp[j] := '/';
  1301. move(temp[1],buffer,length(temp));
  1302. buffer[length(temp)]:=#0;
  1303. asm
  1304. move.l a6,d6
  1305. { we must load the parameters BEFORE setting up the }
  1306. { OS call with a6 }
  1307. lea buffer,a0
  1308. move.l a0,d1
  1309. move.l _DosBase,a6
  1310. jsr _LVOCreateDir(a6)
  1311. tst.l d0
  1312. bne @noerror
  1313. jsr _LVOIoErr(a6)
  1314. move.w d0,errno
  1315. bra @end
  1316. @noerror:
  1317. { Now we must unlock the directory }
  1318. { d0 = lock returned by create dir }
  1319. move.l d0,d1
  1320. jsr _LVOUnlock(a6)
  1321. @end:
  1322. { restore base pointer }
  1323. move.l d6,a6
  1324. end;
  1325. If errno <> 0 then
  1326. Error2InOut;
  1327. end;
  1328. procedure rmdir(const s : string);[IOCheck];
  1329. var
  1330. buffer : array[0..255] of char;
  1331. j : Integer;
  1332. temp : string;
  1333. begin
  1334. { We must check the Ctrl-C before IOChecking of course! }
  1335. if (Setsignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 then
  1336. Begin
  1337. { Clear CTRL-C signal }
  1338. SetSignal(0,SIGBREAKF_CTRL_C);
  1339. Halt(CTRL_C);
  1340. end;
  1341. If InOutRes <> 0 then exit;
  1342. temp:=s;
  1343. for j:=1 to length(temp) do
  1344. if temp[j] = '\' then temp[j] := '/';
  1345. move(temp[1],buffer,length(temp));
  1346. buffer[length(temp)]:=#0;
  1347. do_erase(buffer);
  1348. end;
  1349. procedure chdir(const s : string);[IOCheck];
  1350. var
  1351. buffer : array[0..255] of char;
  1352. alock : longint;
  1353. FIB :pFileInfoBlock;
  1354. j: integer;
  1355. temp : string;
  1356. begin
  1357. if (Setsignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 then
  1358. Begin
  1359. { Clear CTRL-C signal }
  1360. SetSignal(0,SIGBREAKF_CTRL_C);
  1361. Halt(CTRL_C);
  1362. end;
  1363. If InOutRes <> 0 then exit;
  1364. temp:=s;
  1365. for j:=1 to length(temp) do
  1366. if temp[j] = '\' then temp[j] := '/';
  1367. { Return parent directory }
  1368. if s = '..' then
  1369. Begin
  1370. getdir(0,temp);
  1371. j:=length(temp);
  1372. { Look through the previous paths }
  1373. while (temp[j] <> '/') AND (temp[j] <> ':') AND (j > 0 ) do
  1374. dec(j);
  1375. if j > 0 then
  1376. temp:=copy(temp,1,j);
  1377. end;
  1378. alock := 0;
  1379. fib:=nil;
  1380. new(fib);
  1381. move(temp[1],buffer,length(temp));
  1382. buffer[length(temp)]:=#0;
  1383. { Changing the directory is a pretty complicated affair }
  1384. { 1) Obtain a lock on the directory }
  1385. { 2) CurrentDir the lock }
  1386. asm
  1387. lea buffer,a0
  1388. move.l a0,d1 { pointer to buffer in d1 }
  1389. move.l d2,-(sp) { save d2 register }
  1390. move.l #-2,d2 { ACCESS_READ lock }
  1391. move.l a6,d6 { Save base pointer }
  1392. move.l _DosBase,a6
  1393. jsr _LVOLock(a6){ Lock the directory }
  1394. move.l (sp)+,d2 { Restore d2 register }
  1395. tst.l d0 { zero = error! }
  1396. bne @noerror
  1397. jsr _LVOIoErr(a6)
  1398. move.w d0,errno
  1399. move.l d6,a6 { reset base pointer }
  1400. bra @End
  1401. @noerror:
  1402. move.l d6,a6 { reset base pointer }
  1403. move.l d0,alock { save the lock }
  1404. @End:
  1405. end;
  1406. If errno <> 0 then
  1407. Begin
  1408. Error2InOut;
  1409. exit;
  1410. end;
  1411. if (Examine(alock, fib^) = TRUE) AND (fib^.fib_DirEntryType > 0) then
  1412. Begin
  1413. alock := CurrentDir(alock);
  1414. if OrigDir = 0 then
  1415. Begin
  1416. OrigDir := alock;
  1417. alock := 0;
  1418. end;
  1419. end;
  1420. if alock <> 0 then
  1421. Unlock(alock);
  1422. if assigned(fib) then dispose(fib);
  1423. end;
  1424. Procedure GetCwd(var path: string);
  1425. var
  1426. lock: longint;
  1427. fib: PfileInfoBlock;
  1428. len : integer;
  1429. newlock : longint;
  1430. elen : integer;
  1431. Process : PProcess;
  1432. Begin
  1433. len := 0;
  1434. path := '';
  1435. fib := nil;
  1436. { By using a pointer instead of a local variable}
  1437. { we are assured that the pointer is aligned on }
  1438. { a dword boundary. }
  1439. new(fib);
  1440. Process := FindTask(nil);
  1441. if (process^.pr_Task.tc_Node.ln_Type = NT_TASK) then
  1442. Begin
  1443. path:='';
  1444. exit;
  1445. end;
  1446. lock := DupLock(process^.pr_CurrentDir);
  1447. if (Lock = 0) then
  1448. Begin
  1449. path:='';
  1450. exit;
  1451. end;
  1452. While (lock <> 0) and (Examine(lock,FIB^) = TRUE) do
  1453. Begin
  1454. elen := strlen(fib^.fib_FileName);
  1455. if (len + elen + 2 > 255) then
  1456. break;
  1457. newlock := ParentDir(lock);
  1458. if (len <> 0) then
  1459. Begin
  1460. if (newlock <> 0) then
  1461. path:='/'+path
  1462. else
  1463. path:=':'+path;
  1464. path:=strpas(fib^.fib_FileName)+path;
  1465. Inc(len);
  1466. end
  1467. else
  1468. Begin
  1469. path:=strpas(fib^.fib_Filename);
  1470. if (newlock = 0) then
  1471. path:=path+':';
  1472. end;
  1473. len := len + elen;
  1474. UnLock(lock);
  1475. lock := newlock;
  1476. end;
  1477. if (lock <> 0) then
  1478. Begin
  1479. UnLock(lock);
  1480. path := '';
  1481. end;
  1482. if assigned(fib) then dispose(fib);
  1483. end;
  1484. procedure getdir(drivenr : byte;var dir : string);
  1485. begin
  1486. if (Setsignal(0,0) AND SIGBREAKF_CTRL_C) <> 0 then
  1487. Begin
  1488. { Clear CTRL-C signal }
  1489. SetSignal(0,SIGBREAKF_CTRL_C);
  1490. Halt(CTRL_C);
  1491. end;
  1492. GetCwd(dir);
  1493. If errno <> 0 then
  1494. Error2InOut;
  1495. end;
  1496. {*****************************************************************************
  1497. SystemUnit Initialization
  1498. *****************************************************************************}
  1499. Procedure Startup; Assembler;
  1500. asm
  1501. move.l a6,d6 { save a6 }
  1502. move.l (4),a6 { get ExecBase pointer }
  1503. move.l a6,_ExecBase
  1504. suba.l a1,a1
  1505. jsr _LVOFindTask(a6)
  1506. move.l d0,a0
  1507. { Check the stack value }
  1508. { are we running from a CLI? }
  1509. tst.l 172(a0) { 172 = pr_CLI }
  1510. bne @fromCLI
  1511. { we do not support Workbench yet .. }
  1512. move.l d6,a6 { restore a6 }
  1513. move.l #1,d0
  1514. jsr HALT_ERROR
  1515. @fromCLI:
  1516. { Open the following libraries: }
  1517. { Intuition.library }
  1518. { dos.library }
  1519. moveq.l #0,d0
  1520. move.l intuitionname,a1 { directly since it is a pchar }
  1521. jsr _LVOOpenLibrary(a6)
  1522. move.l d0,_IntuitionBase
  1523. beq @exitprg
  1524. moveq.l #0,d0
  1525. move.l utilityname,a1 { directly since it is a pchar }
  1526. jsr _LVOOpenLibrary(a6)
  1527. move.l d0,_UtilityBase
  1528. beq @exitprg
  1529. moveq.l #0,d0
  1530. move.l dosname,a1 { directly since it is a pchar }
  1531. jsr _LVOOpenLibrary(a6)
  1532. move.l d0,_DOSBase
  1533. beq @exitprg
  1534. { Find standard input and output }
  1535. { for CLI }
  1536. @OpenFiles:
  1537. move.l _DOSBase,a6
  1538. jsr _LVOInput(a6) { get standard in }
  1539. move.l d0, StdInputHandle { save standard Input handle }
  1540. { move.l d0,d1 }{ set up for next call }
  1541. { jsr _LVOIsInteractive(a6)}{ is it interactive? }
  1542. { move.l #_Input,a0 }{ get file record again }
  1543. { move.b d0,INTERACTIVE(a0) }{ set flag }
  1544. { beq StdInNotInteractive }{ skip this if not interactive }
  1545. { move.l BUFFER(a0),a1 }{ get buffer address }
  1546. { add.l #1,a1 }{ make end one byte further on }
  1547. { move.l a1,MAX(a0) }{ set buffer size }
  1548. { move.l a1,CURRENT(a0) }{ will need a read }
  1549. bra @OpenStdOutput
  1550. @StdInNotInteractive
  1551. { jsr _p%FillBuffer } { fill the buffer }
  1552. @OpenStdOutput
  1553. jsr _LVOOutput(a6) { get ouput file handle }
  1554. move.l d0,StdOutputHandle { get file record }
  1555. bra @startupend
  1556. { move.l d0,d1 } { set up for call }
  1557. { jsr _LVOIsInteractive(a6) } { is it interactive? }
  1558. { move.l #_Output,a0 } { get file record }
  1559. { move.b d0,INTERACTIVE(a0)} { set flag }
  1560. @exitprg:
  1561. move.l d6,a6 { restore a6 }
  1562. move.l #219,d0
  1563. jsr HALT_ERROR
  1564. @startupend:
  1565. move.l d6,a6 { restore a6 }
  1566. end;
  1567. begin
  1568. errno:= 0;
  1569. FromHalt := FALSE;
  1570. { Initial state is on -- in case of RunErrors before the i/o handles are }
  1571. { ok. }
  1572. Initial:=TRUE;
  1573. { Initialize ExitProc }
  1574. ExitProc:=Nil;
  1575. Startup;
  1576. { to test stack depth }
  1577. loweststack:=maxlongint;
  1578. { Setup heap }
  1579. InitHeap;
  1580. { Setup stdin, stdout and stderr }
  1581. OpenStdIO(Input,fmInput,StdInputHandle);
  1582. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1583. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1584. { The Amiga does not seem to have a StdError }
  1585. { handle, therefore make the StdError handle }
  1586. { equal to the StdOutputHandle. }
  1587. StdErrorHandle := StdOutputHandle;
  1588. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1589. { Now Handles and function handlers are setup }
  1590. { correctly. }
  1591. Initial:=FALSE;
  1592. { Reset IO Error }
  1593. InOutRes:=0;
  1594. { Startup }
  1595. { Only AmigaOS v2.04 or greater is supported }
  1596. If KickVersion < 36 then
  1597. Begin
  1598. WriteLn('v36 or greater of Kickstart required.');
  1599. Halt(1);
  1600. end;
  1601. argc:=GetParamCount(args);
  1602. OrigDir := 0;
  1603. FileList := nil;
  1604. end.
  1605. {
  1606. $Log$
  1607. Revision 1.15 2000-01-07 16:41:29 daniel
  1608. * copyright 2000
  1609. Revision 1.14 2000/01/07 16:32:22 daniel
  1610. * copyright 2000 added
  1611. Revision 1.13 1999/09/10 15:40:32 peter
  1612. * fixed do_open flags to be > $100, becuase filemode can be upto 255
  1613. Revision 1.12 1999/01/18 10:05:47 pierre
  1614. + system_exit procedure added
  1615. Revision 1.11 1998/12/28 15:50:42 peter
  1616. + stdout, which is needed when you write something in the system unit
  1617. to the screen. Like the runtime error
  1618. Revision 1.10 1998/09/14 10:48:00 peter
  1619. * FPC_ names
  1620. * Heap manager is now system independent
  1621. Revision 1.9 1998/08/17 12:34:22 carl
  1622. * chdir accepts .. characters
  1623. + added ctrl-c checking
  1624. + implemented sbrk
  1625. * exit code was never called if no error was found on exit!
  1626. * register was not saved in do_open
  1627. Revision 1.8 1998/07/13 12:32:18 carl
  1628. * do_truncate works, some cleanup
  1629. Revision 1.6 1998/07/02 12:37:52 carl
  1630. * IOCheck for chdir,rmdir and mkdir as in TP
  1631. Revision 1.5 1998/07/01 14:30:56 carl
  1632. * forgot that includes are case sensitive
  1633. Revision 1.4 1998/07/01 14:13:50 carl
  1634. * do_open bugfix
  1635. * correct conversion of Amiga error codes to TP error codes
  1636. * InoutRes word bugfix
  1637. * parameter counting fixed
  1638. * new stack checking implemented
  1639. + IOCheck for chdir,rmdir,getdir and rmdir
  1640. * do_filepos was wrong
  1641. + chdir correctly implemented
  1642. * getdir correctly implemented
  1643. Revision 1.1.1.1 1998/03/25 11:18:47 root
  1644. * Restored version
  1645. Revision 1.14 1998/03/21 04:20:09 carl
  1646. * correct ExecBase pointer (from Nils Sjoholm)
  1647. * correct OpenLibrary vector (from Nils Sjoholm)
  1648. Revision 1.13 1998/03/14 21:34:32 carl
  1649. * forgot to save a6 in Startup routine
  1650. Revision 1.12 1998/02/24 21:19:42 carl
  1651. *** empty log message ***
  1652. Revision 1.11 1998/02/23 02:22:49 carl
  1653. * bugfix if linking problems
  1654. Revision 1.9 1998/02/06 16:34:32 carl
  1655. + do_open is now standard with other platforms
  1656. Revision 1.8 1998/02/02 15:01:45 carl
  1657. * fixed bug with opening library versions (from Nils Sjoholm)
  1658. Revision 1.7 1998/01/31 19:35:19 carl
  1659. + added opening of utility.library
  1660. Revision 1.6 1998/01/29 23:20:54 peter
  1661. - Removed Backslash convert
  1662. Revision 1.5 1998/01/27 10:55:04 peter
  1663. * Amiga uses / not \, so change AllowSlash -> AllowBackSlash
  1664. Revision 1.4 1998/01/25 21:53:20 peter
  1665. + Universal Handles support for StdIn/StdOut/StdErr
  1666. * Updated layout of sysamiga.pas
  1667. Revision 1.3 1998/01/24 21:09:53 carl
  1668. + added missing input/output function pointers
  1669. Revision 1.2 1998/01/24 14:08:25 carl
  1670. * RunError 217 --> RunError 219 (cannot open lib)
  1671. + Standard Handle names implemented
  1672. Revision 1.1 1998/01/24 05:12:15 carl
  1673. + initial revision, some stuff still missing though.
  1674. (and as you might imagine ... untested :))
  1675. }