system.pas 53 KB

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