sysatari.pas 16 KB

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