system.pas 19 KB

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