system.pas 53 KB

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