2
0

sysatari.pas 18 KB

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