sysatari.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 by the Free Pascal development team.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$define ATARI}
  12. unit sysatari;
  13. { Left to do : }
  14. { - Fix DOSError codes to conform to those of DOS (TP) }
  15. {$I os.inc}
  16. interface
  17. { used for single computations }
  18. const BIAS4 = $7f-1;
  19. {$I systemh.inc}
  20. {$I heaph.inc}
  21. const
  22. UnusedHandle = $ffff;
  23. StdInputHandle = 0;
  24. StdOutputHandle = 1;
  25. StdErrorHandle = $ffff;
  26. implementation
  27. {$I system.inc}
  28. {$I lowmath.inc}
  29. type
  30. plongint = ^longint;
  31. {$S-}
  32. procedure Stack_Check; assembler;
  33. { Check for local variable allocation }
  34. { On Entry -> d0 : size of local stack we are trying to allocate }
  35. asm
  36. XDEF STACKCHECK
  37. move.l sp,d1 { get value of stack pointer }
  38. sub.l d0,d1 { sp - stack_size }
  39. cmp.l __BREAK,d1
  40. bgt @st1nosweat
  41. move.l #202,d0
  42. jsr HALT_ERROR
  43. @st1nosweat:
  44. end;
  45. procedure halt(errnum : byte);
  46. begin
  47. do_exit;
  48. flush(stderr);
  49. asm
  50. clr.l d0
  51. move.b errnum,d0
  52. move.w d0,-(sp)
  53. move.w #$4c,-(sp)
  54. trap #1
  55. end;
  56. end;
  57. function paramcount : longint; assembler;
  58. asm
  59. clr.l d0
  60. move.w __ARGC,d0
  61. sub.w #1,d0
  62. end;
  63. function paramstr(l : longint) : string;
  64. function args : pointer; assembler;
  65. asm
  66. move.l __ARGS,d0
  67. end;
  68. var
  69. p : ^pchar;
  70. begin
  71. if (l>=0) and (l<=paramcount) then
  72. begin
  73. p:=args;
  74. paramstr:=strpas(p[l]);
  75. end
  76. else paramstr:='';
  77. end;
  78. procedure randomize;
  79. var
  80. hl : longint;
  81. begin
  82. asm
  83. movem.l d2/d3/a2/a3, -(sp) { save OS registers }
  84. move.w #17,-(sp)
  85. trap #14 { call xbios - random number }
  86. add.l #2,sp
  87. movem.l (sp)+,d2/d3/a2/a3
  88. move.l d0,hl { result in d0 }
  89. end;
  90. randseed:=hl;
  91. end;
  92. { This routine is used to grow the heap. }
  93. { But here we do a trick, we say that the }
  94. { heap cannot be regrown! }
  95. function sbrk( size: longint): longint;
  96. { on exit -1 = if fails. }
  97. Begin
  98. sbrk:=-1;
  99. end;
  100. {$I heap.inc}
  101. {****************************************************************************
  102. Low Level File Routines
  103. ****************************************************************************}
  104. procedure AllowSlash(p:pchar);
  105. var
  106. i : longint;
  107. begin
  108. { allow slash as backslash }
  109. for i:=0 to strlen(p) do
  110. if p[i]='/' then p[i]:='\';
  111. end;
  112. procedure do_close(h : longint);
  113. begin
  114. asm
  115. movem.l d2/d3/a2/a3,-(sp)
  116. move.l h,-(sp)
  117. move.w #$3e,-(sp)
  118. trap #1
  119. add.l #4,sp { restore stack ... }
  120. movem.l (sp)+,d2/d3/a2/a3
  121. end;
  122. end;
  123. procedure do_erase(p : pchar);
  124. begin
  125. AllowSlash(p);
  126. asm
  127. move.l d2,d6 { save d2 }
  128. movem.l d3/a2/a3,-(sp) { save regs }
  129. move.l p,-(sp)
  130. move.w #$41,-(sp)
  131. trap #1
  132. add.l #6,sp
  133. move.l d6,d2 { restore d2 }
  134. movem.l (sp)+,d3/a2/a3
  135. tst.w d0
  136. beq @doserend
  137. move.w d0,InOutRes
  138. @doserend:
  139. end;
  140. end;
  141. procedure do_rename(p1,p2 : pchar);
  142. begin
  143. AllowSlash(p1);
  144. AllowSlash(p2);
  145. asm
  146. move.l d2,d6 { save d2 }
  147. movem.l d3/a2/a3,-(sp)
  148. move.l p1,-(sp)
  149. move.l p2,-(sp)
  150. clr.w -(sp)
  151. move.w #$56,-(sp)
  152. trap #1
  153. lea 12(sp),sp
  154. move.l d6,d2 { restore d2 }
  155. movem.l (sp)+,d3/a2/a3
  156. tst.w d0
  157. beq @dosreend
  158. move.w d0,InOutRes { error ... }
  159. @dosreend:
  160. end;
  161. end;
  162. function do_isdevice(handle:longint):boolean;
  163. begin
  164. if (handle=stdoutputhandle) or (handle=stdinputhandle) or
  165. (handle=stderrorhandle) then
  166. do_isdevice:=FALSE;
  167. else
  168. do_isdevice:=TRUE;
  169. end;
  170. function do_write(h,addr,len : longint) : longint;
  171. begin
  172. asm
  173. move.l d2,d6 { save d2 }
  174. movem.l d3/a2/a3,-(sp)
  175. move.l addr,-(sp)
  176. move.l len,-(sp)
  177. move.w h,-(sp)
  178. move.w #$40,-(sp)
  179. trap #1
  180. lea 12(sp),sp
  181. move.l d6,d2 { restore d2 }
  182. movem.l (sp)+,d3/a2/a3
  183. tst.l d0
  184. bpl @doswrend
  185. move.w d0,InOutRes { error ... }
  186. @doswrend:
  187. move.l d0,@RESULT
  188. end;
  189. end;
  190. function do_read(h,addr,len : longint) : longint;
  191. begin
  192. asm
  193. move.l d2,d6 { save d2 }
  194. movem.l d3/a2/a3,-(sp)
  195. move.l addr,-(sp)
  196. move.l len,-(sp)
  197. move.w h,-(sp)
  198. move.w #$40,-(sp)
  199. trap #1
  200. lea 12(sp),sp
  201. move.l d6,d2 { restore d2 }
  202. movem.l (sp)+,d3/a2/a3
  203. tst.l d0
  204. bpl @dosrdend
  205. move.w d0,InOutRes { error ... }
  206. @dosrdend:
  207. move.l d0,@Result
  208. end;
  209. end;
  210. function do_filepos(handle : longint) : longint;
  211. begin
  212. asm
  213. move.l d2,d6 { save d2 }
  214. movem.l d3/a2/a3,-(sp)
  215. move.w #1,-(sp) { seek from current position }
  216. move.w handle,-(sp)
  217. move.l #0,-(sp) { with a seek offset of zero }
  218. move.w #$42,-(sp)
  219. trap #1
  220. lea 10(sp),sp
  221. move.l d6,d2 { restore d2 }
  222. movem.l (sp)+,d3/a2/a3
  223. move.l d0,@Result
  224. end;
  225. end;
  226. procedure do_seek(handle,pos : longint);
  227. begin
  228. asm
  229. move.l d2,d6 { save d2 }
  230. movem.l d3/a2/a3,-(sp)
  231. move.w #0,-(sp) { seek from start of file }
  232. move.w handle,-(sp)
  233. move.l pos,-(sp)
  234. move.w #$42,-(sp)
  235. trap #1
  236. lea 10(sp),sp
  237. move.l d6,d2 { restore d2 }
  238. movem.l (sp)+,d3/a2/a3
  239. end;
  240. end;
  241. function do_seekend(handle:longint):longint;
  242. var
  243. t: longint;
  244. begin
  245. asm
  246. move.l d2,d6 { save d2 }
  247. movem.l d3/a2/a3,-(sp)
  248. move.w #2,-(sp) { seek from end of file }
  249. move.w handle,-(sp)
  250. move.l #0,-(sp) { with an offset of 0 from end }
  251. move.w #$42,-(sp)
  252. trap #1
  253. lea 10(sp),sp
  254. move.l d6,d2 { restore d2 }
  255. movem.l (sp)+,d3/a2/a3
  256. move.l d0,t
  257. end;
  258. do_seekend:=t;
  259. end;
  260. function do_filesize(handle : longint) : longint;
  261. var
  262. aktfilepos : longint;
  263. begin
  264. aktfilepos:=do_filepos(handle);
  265. do_filesize:=do_seekend(handle);
  266. do_seek(handle,aktfilepos);
  267. end;
  268. procedure do_truncate (handle,pos:longint);
  269. begin
  270. do_seek(handle,pos);
  271. {!!!!!!!!!!!!}
  272. end;
  273. procedure do_open(var f;p:pchar;flags:longint);
  274. {
  275. filerec and textrec have both handle and mode as the first items so
  276. they could use the same routine for opening/creating.
  277. when (flags and $10) the file will be append
  278. when (flags and $100) the file will be truncate/rewritten
  279. when (flags and $1000) there is no check for close (needed for textfiles)
  280. }
  281. var
  282. i : longint;
  283. oflags: longint;
  284. begin
  285. AllowSlash(p);
  286. { close first if opened }
  287. if ((flags and $1000)=0) then
  288. begin
  289. case filerec(f).mode of
  290. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  291. fmclosed : ;
  292. else
  293. begin
  294. inoutres:=102; {not assigned}
  295. exit;
  296. end;
  297. end;
  298. end;
  299. { reset file handle }
  300. filerec(f).handle:=UnusedHandle;
  301. oflags:=$04;
  302. { convert filemode to filerec modes }
  303. case (flags and 3) of
  304. 0 : begin
  305. filerec(f).mode:=fminput;
  306. oflags:=$01;
  307. end;
  308. 1 : filerec(f).mode:=fmoutput;
  309. 2 : filerec(f).mode:=fminout;
  310. end;
  311. if (flags and $100)<>0 then
  312. begin
  313. filerec(f).mode:=fmoutput;
  314. oflags:=$02;
  315. end
  316. else
  317. if (flags and $10)<>0 then
  318. begin
  319. filerec(f).mode:=fmoutput;
  320. oflags:=$04;
  321. end;
  322. { empty name is special }
  323. if p[0]=#0 then
  324. begin
  325. case filerec(f).mode of
  326. fminput : filerec(f).handle:=StdInputHandle;
  327. fmappend,
  328. fmoutput : begin
  329. filerec(f).handle:=StdOutputHandle;
  330. filerec(f).mode:=fmoutput; {fool fmappend}
  331. end;
  332. end;
  333. exit;
  334. end;
  335. asm
  336. movem.l d2/d3/a2/a3,-(sp) { save used registers }
  337. cmp.l #4,oflags { check if append mode ... }
  338. bne @opencont2
  339. move.w #2,d0 { append mode... r/w open }
  340. bra @opencont1
  341. @opencont2:
  342. move.l oflags,d0 { use flag as source ... }
  343. @opencont1:
  344. move.w d0,-(sp)
  345. pea p
  346. move.w #$3d,-(sp)
  347. trap #1
  348. add.l #8,sp { restore stack of os call }
  349. movem.l (sp)+,d2/d3/a2/a3
  350. tst.l d0
  351. bpl @opennoerr
  352. move.w d0,InOutRes
  353. @opennoerr:
  354. move.l d0,i { get handle ... }
  355. end;
  356. filerec(f).handle:=i;
  357. if (flags and $10)<>0 then
  358. do_seekend(filerec(f).handle);
  359. end;
  360. {*****************************************************************************
  361. UnTyped File Handling
  362. *****************************************************************************}
  363. {$i file.inc}
  364. {*****************************************************************************
  365. Typed File Handling
  366. *****************************************************************************}
  367. {$i typefile.inc}
  368. {*****************************************************************************
  369. Text File Handling
  370. *****************************************************************************}
  371. {$i text.inc}
  372. {*****************************************************************************
  373. Directory Handling
  374. *****************************************************************************}
  375. procedure DosDir(func:byte;const s:string);
  376. var
  377. buffer : array[0..255] of char;
  378. begin
  379. move(s[1],buffer,length(s));
  380. buffer[length(s)]:=#0;
  381. AllowSlash(pchar(@buffer));
  382. asm
  383. move.l d2,d6 { save d2 }
  384. movem.l d3/a2/a3,-(sp)
  385. pea buffer
  386. move.b func,-(sp)
  387. trap #1
  388. add.l #6,sp
  389. move.l d6,d2 { restore d2 }
  390. movem.l (sp)+,d3/a2/a3
  391. tst.w d0
  392. beq @dosdirend
  393. move.w d0,InOutRes
  394. @dosdirend:
  395. end;
  396. end;
  397. procedure mkdir(const s : string);[IOCheck];
  398. begin
  399. If InOutRes <> 0 then exit;
  400. DosDir($39,s);
  401. end;
  402. procedure rmdir(const s : string);[IOCheck];
  403. begin
  404. If InOutRes <> 0 then exit;
  405. DosDir($3a,s);
  406. end;
  407. procedure chdir(const s : string);[IOCheck];
  408. begin
  409. If InOutRes <> 0 then exit;
  410. DosDir($3b,s);
  411. end;
  412. procedure getdir(drivenr : byte;var dir : string);
  413. var
  414. temp : array[0..255] of char;
  415. sof : pchar;
  416. i : longint;
  417. begin
  418. sof:=pchar(@dir[4]);
  419. asm
  420. move.l d2,d6 { save d2 }
  421. movem.l d3/a2/a3,-(sp)
  422. { Get dir from drivenr : 0=default, 1=A etc... }
  423. move.w drivenr,-(sp)
  424. { put (previously saved) offset in si }
  425. pea dir
  426. { call attos function 47H : Get dir }
  427. move.w #$47,-(sp)
  428. { make the call }
  429. trap #1
  430. add.l #8,sp
  431. move.l d6,d2 { restore d2 }
  432. movem.l (sp)+,d3/a2/a3
  433. end;
  434. { Now Dir should be filled with directory in ASCIIZ, }
  435. { starting from dir[4] }
  436. dir[0]:=#3;
  437. dir[2]:=':';
  438. dir[3]:='\';
  439. i:=4;
  440. { conversation to Pascal string }
  441. while (dir[i]<>#0) do
  442. begin
  443. { convert path name to DOS }
  444. if dir[i]='/' then
  445. dir[i]:='\';
  446. dir[0]:=chr(i);
  447. inc(i);
  448. end;
  449. { upcase the string (FPKPascal function) }
  450. dir:=upcase(dir);
  451. if drivenr<>0 then { Drive was supplied. We know it }
  452. dir[1]:=chr(65+drivenr-1)
  453. else
  454. begin
  455. asm
  456. move.l d2,d6 { save d2 }
  457. movem.l d3/a2/a3,-(sp)
  458. move.w #$19,-(sp)
  459. trap #1
  460. add.l #2,sp
  461. move.l d6,d2 { restore d2 }
  462. movem.l (sp)+,d3/a2/a3
  463. end;
  464. dir[1]:=chr(i);
  465. end;
  466. end;
  467. {*****************************************************************************
  468. SystemUnit Initialization
  469. *****************************************************************************}
  470. begin
  471. { Initialize ExitProc }
  472. ExitProc:=Nil;
  473. { to test stack depth }
  474. loweststack:=maxlongint;
  475. { Setup heap }
  476. InitHeap;
  477. { Setup stdin, stdout and stderr }
  478. OpenStdIO(Input,fmInput,StdInputHandle);
  479. OpenStdIO(Output,fmOutput,StdOutputHandle);
  480. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  481. { Reset IO Error }
  482. InOutRes:=0;
  483. end.
  484. {
  485. $Log$
  486. Revision 1.4 1998-07-02 12:39:27 carl
  487. * IOCheck for mkdir,chdir and rmdir, just like in TP
  488. Revision 1.3 1998/07/01 14:40:20 carl
  489. + new stack checking implemented
  490. + IOCheck for chdir , getdir , mkdir and rmdir
  491. Revision 1.1.1.1 1998/03/25 11:18:47 root
  492. * Restored version
  493. Revision 1.8 1998/02/23 02:27:39 carl
  494. * make it link correctly
  495. Revision 1.7 1998/02/06 16:33:02 carl
  496. * oops... commited wrong file
  497. + do_open is now standard with other platforms
  498. Revision 1.5 1998/01/31 19:32:51 carl
  499. - removed incorrect $define
  500. Revision 1.4 1998/01/27 10:55:45 peter
  501. * Word Handles from -1 -> $ffff
  502. Revision 1.3 1998/01/25 22:44:14 peter
  503. * Using uniform layout
  504. }