system.pas 19 KB

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