system.pp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl,
  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. unit system;
  13. interface
  14. { include system-independent routine headers }
  15. {$I systemh.inc}
  16. { include heap support headers }
  17. {$I heaph.inc}
  18. {Platform specific information}
  19. const
  20. LineEnding = #13#10;
  21. { LFNSupport is a variable here, defined below!!! }
  22. DirectorySeparator = '\';
  23. DriveSeparator = ':';
  24. PathSeparator = ';';
  25. FileNameCaseSensitive = false;
  26. const
  27. { Default filehandles }
  28. UnusedHandle = $ffff;
  29. StdInputHandle = 0;
  30. StdOutputHandle = 1;
  31. StdErrorHandle = 2;
  32. { Default memory segments (Tp7 compatibility) }
  33. seg0040 = $0040;
  34. segA000 = $A000;
  35. segB000 = $B000;
  36. segB800 = $B800;
  37. var
  38. { C-compatible arguments and environment }
  39. argc : longint;
  40. argv : ppchar;
  41. envp : ppchar;
  42. type
  43. { Dos Extender info }
  44. p_stub_info = ^t_stub_info;
  45. t_stub_info = packed record
  46. magic : array[0..15] of char;
  47. size : longint;
  48. minstack : longint;
  49. memory_handle : longint;
  50. initial_size : longint;
  51. minkeep : word;
  52. ds_selector : word;
  53. ds_segment : word;
  54. psp_selector : word;
  55. cs_selector : word;
  56. env_size : word;
  57. basename : array[0..7] of char;
  58. argv0 : array [0..15] of char;
  59. dpmi_server : array [0..15] of char;
  60. end;
  61. t_go32_info_block = packed record
  62. size_of_this_structure_in_bytes : longint; {offset 0}
  63. linear_address_of_primary_screen : longint; {offset 4}
  64. linear_address_of_secondary_screen : longint; {offset 8}
  65. linear_address_of_transfer_buffer : longint; {offset 12}
  66. size_of_transfer_buffer : longint; {offset 16}
  67. pid : longint; {offset 20}
  68. master_interrupt_controller_base : byte; {offset 24}
  69. slave_interrupt_controller_base : byte; {offset 25}
  70. selector_for_linear_memory : word; {offset 26}
  71. linear_address_of_stub_info_structure : longint; {offset 28}
  72. linear_address_of_original_psp : longint; {offset 32}
  73. run_mode : word; {offset 36}
  74. run_mode_info : word; {offset 38}
  75. end;
  76. var
  77. stub_info : p_stub_info;
  78. go32_info_block : t_go32_info_block;
  79. LFNSupport : boolean;
  80. { Needed for CRT unit }
  81. function do_read(h,addr,len : longint) : longint;
  82. implementation
  83. { include system independent routines }
  84. {$I system.inc}
  85. {$ASMMODE DIRECT}
  86. procedure int_stackcheck(stack_size:longint);[public,alias:'FPC_STACKCHECK'];
  87. begin
  88. { called when trying to get local stack
  89. if the compiler directive $S is set
  90. this function must preserve esi !!!!
  91. because esi is set by the calling
  92. proc for methods
  93. it must preserve all registers !!
  94. With a 2048 byte safe area used to write to StdIo without crossing
  95. the stack boundary
  96. }
  97. asm
  98. pushl %eax
  99. pushl %ebx
  100. movl stack_size,%ebx
  101. addl $2048,%ebx
  102. movl %esp,%eax
  103. subl %ebx,%eax
  104. {$ifdef SYSTEMDEBUG}
  105. movl U_SYSTEM_LOWESTSTACK,%ebx
  106. cmpl %eax,%ebx
  107. jb _is_not_lowest
  108. movl %eax,U_SYSTEM_LOWESTSTACK
  109. _is_not_lowest:
  110. {$endif SYSTEMDEBUG}
  111. movl __stkbottom,%ebx
  112. cmpl %eax,%ebx
  113. jae __short_on_stack
  114. popl %ebx
  115. popl %eax
  116. leave
  117. ret $4
  118. __short_on_stack:
  119. { can be usefull for error recovery !! }
  120. popl %ebx
  121. popl %eax
  122. end['EAX','EBX'];
  123. HandleError(202);
  124. end;
  125. function paramcount : longint;
  126. begin
  127. paramcount := argc - 1;
  128. end;
  129. function paramstr(l : longint) : string;
  130. begin
  131. if (l>=0) and (l+1<=argc) then
  132. paramstr:=strpas(argv[l])
  133. else
  134. paramstr:='';
  135. end;
  136. procedure randomize;
  137. Begin
  138. asm
  139. movb $0x2c,%ah
  140. int $0x21
  141. shll $16,%ecx
  142. movw %dx,%cx
  143. movl %ecx,randseed
  144. end;
  145. end;
  146. {*****************************************************************************
  147. Heap Management
  148. *****************************************************************************}
  149. function getheapstart:pointer;assembler;
  150. asm
  151. leal HEAP,%eax
  152. end ['EAX'];
  153. function getheapsize:longint;assembler;
  154. asm
  155. movl HEAPSIZE,%eax
  156. end ['EAX'];
  157. function Sbrk(size : longint) : longint;assembler;
  158. asm
  159. movl size,%ebx
  160. movl $0x4a01,%eax
  161. int $0x21
  162. end;
  163. { include standard heap management }
  164. {$I heap.inc}
  165. {****************************************************************************
  166. Low Level File Routines
  167. ****************************************************************************}
  168. procedure AllowSlash(p:pchar);
  169. var
  170. i : longint;
  171. begin
  172. { allow slash as backslash }
  173. for i:=0 to strlen(p) do
  174. if p[i]='/' then p[i]:='\';
  175. end;
  176. procedure do_close(h : longint);assembler;
  177. asm
  178. movl h,%ebx
  179. movb $0x3e,%ah
  180. pushl %ebp
  181. int $0x21
  182. popl %ebp
  183. jnc .LCLOSE1
  184. movw %ax,inoutres
  185. .LCLOSE1:
  186. end;
  187. procedure do_erase(p : pchar);
  188. begin
  189. AllowSlash(p);
  190. asm
  191. movl p,%edx
  192. movb $0x41,%ah
  193. pushl %ebp
  194. int $0x21
  195. popl %ebp
  196. jnc .LERASE1
  197. movw %ax,inoutres
  198. .LERASE1:
  199. end;
  200. end;
  201. procedure do_rename(p1,p2 : pchar);
  202. begin
  203. AllowSlash(p1);
  204. AllowSlash(p2);
  205. asm
  206. movl p1,%edx
  207. movl p2,%edi
  208. movb $0x56,%ah
  209. pushl %ebp
  210. int $0x21
  211. popl %ebp
  212. jnc .LRENAME1
  213. movw %ax,inoutres
  214. .LRENAME1:
  215. end;
  216. end;
  217. function do_write(h,addr,len : longint) : longint;assembler;
  218. asm
  219. movl len,%ecx
  220. movl addr,%edx
  221. movl h,%ebx
  222. movb $0x40,%ah
  223. int $0x21
  224. jnc .LDOSWRITE1
  225. movw %ax,inoutres
  226. xorl %eax,%eax
  227. .LDOSWRITE1:
  228. end;
  229. function do_read(h,addr,len : longint) : longint;assembler;
  230. asm
  231. movl len,%ecx
  232. movl addr,%edx
  233. movl h,%ebx
  234. movb $0x3f,%ah
  235. int $0x21
  236. jnc .LDOSREAD1
  237. movw %ax,inoutres
  238. xorl %eax,%eax
  239. .LDOSREAD1:
  240. end;
  241. function do_filepos(handle : longint) : longint;assembler;
  242. asm
  243. movl $0x4201,%eax
  244. movl handle,%ebx
  245. xorl %ecx,%ecx
  246. xorl %edx,%edx
  247. pushl %ebp
  248. int $0x21
  249. popl %ebp
  250. jnc .LDOSFILEPOS1
  251. movw %ax,inoutres
  252. xorl %eax,%eax
  253. jmp .LDOSFILEPOS2
  254. .LDOSFILEPOS1:
  255. shll $16,%edx
  256. movzwl %ax,%eax
  257. orl %edx,%eax
  258. .LDOSFILEPOS2:
  259. end;
  260. procedure do_seek(handle,pos : longint);assembler;
  261. asm
  262. movl $0x4200,%eax
  263. movl handle,%ebx
  264. movl pos,%edx
  265. movl %edx,%ecx
  266. shrl $16,%ecx
  267. pushl %ebp
  268. int $0x21
  269. popl %ebp
  270. jnc .LDOSSEEK1
  271. movw %ax,inoutres
  272. .LDOSSEEK1:
  273. end;
  274. function do_seekend(handle : longint) : longint;assembler;
  275. asm
  276. movl $0x4202,%eax
  277. movl handle,%ebx
  278. xorl %ecx,%ecx
  279. xorl %edx,%edx
  280. pushl %ebp
  281. int $0x21
  282. popl %ebp
  283. jnc .Lset_at_end1
  284. movw %ax,inoutres
  285. xorl %eax,%eax
  286. jmp .Lset_at_end2
  287. .Lset_at_end1:
  288. shll $16,%edx
  289. movzwl %ax,%eax
  290. orl %edx,%eax
  291. .Lset_at_end2:
  292. end;
  293. function do_filesize(handle : longint) : longint;
  294. var
  295. aktfilepos : longint;
  296. begin
  297. aktfilepos:=do_filepos(handle);
  298. do_filesize:=do_seekend(handle);
  299. do_seek(handle,aktfilepos);
  300. end;
  301. procedure do_truncate(handle,pos : longint);assembler;
  302. asm
  303. movl $0x4200,%eax
  304. movl handle,%ebx
  305. movl pos,%edx
  306. movl %edx,%ecx
  307. shrl $16,%ecx
  308. pushl %ebp
  309. int $0x21
  310. popl %ebp
  311. jc .LTruncate1
  312. movl handle,%ebx
  313. movl %ebp,%edx
  314. xorl %ecx,%ecx
  315. movb $0x40,%ah
  316. int $0x21
  317. jnc .LTruncate2
  318. .LTruncate1:
  319. movw %ax,inoutres
  320. .LTruncate2:
  321. end;
  322. procedure do_open(var f;p:pchar;flags:longint);
  323. {
  324. filerec and textrec have both handle and mode as the first items so
  325. they could use the same routine for opening/creating.
  326. when (flags and $100) the file will be append
  327. when (flags and $1000) the file will be truncate/rewritten
  328. when (flags and $10000) there is no check for close (needed for textfiles)
  329. }
  330. var
  331. oflags : longint;
  332. begin
  333. AllowSlash(p);
  334. { close first if opened }
  335. if ((flags and $10000)=0) then
  336. begin
  337. case filerec(f).mode of
  338. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  339. fmclosed : ;
  340. else
  341. begin
  342. inoutres:=102; {not assigned}
  343. exit;
  344. end;
  345. end;
  346. end;
  347. { reset file handle }
  348. filerec(f).handle:=UnusedHandle;
  349. oflags:=$8404;
  350. { convert filemode to filerec modes }
  351. case (flags and 3) of
  352. 0 : begin
  353. filerec(f).mode:=fminput;
  354. oflags:=$8001;
  355. end;
  356. 1 : filerec(f).mode:=fmoutput;
  357. 2 : filerec(f).mode:=fminout;
  358. end;
  359. if (flags and $1000)<>0 then
  360. begin
  361. filerec(f).mode:=fmoutput;
  362. oflags:=$8302;
  363. end
  364. else
  365. if (flags and $100)<>0 then
  366. begin
  367. filerec(f).mode:=fmoutput;
  368. oflags:=$8404;
  369. end;
  370. { empty name is special }
  371. if p[0]=#0 then
  372. begin
  373. case FileRec(f).mode of
  374. fminput :
  375. FileRec(f).Handle:=StdInputHandle;
  376. fminout, { this is set by rewrite }
  377. fmoutput :
  378. FileRec(f).Handle:=StdOutputHandle;
  379. fmappend :
  380. begin
  381. FileRec(f).Handle:=StdOutputHandle;
  382. FileRec(f).mode:=fmoutput; {fool fmappend}
  383. end;
  384. end;
  385. exit;
  386. end;
  387. asm
  388. movl $0xff02,%eax
  389. movl oflags,%ecx
  390. movl p,%ebx
  391. int $0x21
  392. jnc .LOPEN1
  393. movw %ax,inoutres
  394. movw $0xffff,%ax
  395. .LOPEN1:
  396. movl f,%edx
  397. movw %ax,(%edx)
  398. end;
  399. if (flags and $100)<>0 then
  400. do_seekend(filerec(f).handle);
  401. end;
  402. function do_isdevice(handle : longint):boolean;assembler;
  403. asm
  404. movl $0x4400,%eax
  405. movl handle,%ebx
  406. pushl %ebp
  407. int $0x21
  408. popl %ebp
  409. jnc .LDOSDEVICE
  410. movw %ax,inoutres
  411. xorl %edx,%edx
  412. .LDOSDEVICE:
  413. movl %edx,%eax
  414. shrl $7,%eax
  415. andl $1,%eax
  416. end;
  417. {*****************************************************************************
  418. UnTyped File Handling
  419. *****************************************************************************}
  420. {$i file.inc}
  421. {*****************************************************************************
  422. Typed File Handling
  423. *****************************************************************************}
  424. {$i typefile.inc}
  425. {*****************************************************************************
  426. Text File Handling
  427. *****************************************************************************}
  428. {$DEFINE EOF_CTRLZ}
  429. {$i text.inc}
  430. {*****************************************************************************
  431. Directory Handling
  432. *****************************************************************************}
  433. procedure DosDir(func:byte;const s:string);
  434. var
  435. buffer : array[0..255] of char;
  436. begin
  437. move(s[1],buffer,length(s));
  438. buffer[length(s)]:=#0;
  439. AllowSlash(pchar(@buffer));
  440. asm
  441. leal buffer,%edx
  442. movb func,%ah
  443. int $0x21
  444. jnc .LDOS_DIRS1
  445. movw %ax,inoutres
  446. .LDOS_DIRS1:
  447. end;
  448. end;
  449. procedure mkdir(const s : string);[IOCheck];
  450. begin
  451. If InOutRes <> 0 then exit;
  452. DosDir($39,s);
  453. end;
  454. procedure rmdir(const s : string);[IOCheck];
  455. begin
  456. If InOutRes <> 0 then exit;
  457. DosDir($3a,s);
  458. end;
  459. procedure chdir(const s : string);[IOCheck];
  460. begin
  461. If InOutRes <> 0 then exit;
  462. DosDir($3b,s);
  463. end;
  464. procedure GetDir (DriveNr: byte; var Dir: ShortString);
  465. var
  466. temp : array[0..255] of char;
  467. sof : pchar;
  468. i : byte;
  469. Err: boolean;
  470. begin
  471. sof:=pchar(@dir[4]);
  472. { dir[1..3] will contain '[drivenr]:\', but is not supplied by DOS,
  473. so we let dos string start at dir[4]
  474. Get dir from drivenr : 0=default, 1=A etc }
  475. asm
  476. movb drivenr,%dl
  477. movl sof,%esi
  478. movw $0x4700,%ax
  479. movb %al,Err
  480. int $0x21
  481. jnc .LGetDir
  482. movw %ax, InOutRes
  483. incb Err
  484. .LGetDir:
  485. end;
  486. if Err and (DriveNr <> 0) then
  487. begin
  488. Dir := char (DriveNr + 64) + ':\';
  489. Exit;
  490. end;
  491. { Now Dir should be filled with directory in ASCIIZ starting from dir[4] }
  492. dir[0]:=#3;
  493. dir[2]:=':';
  494. dir[3]:='\';
  495. i:=4;
  496. { conversation to Pascal string }
  497. while (dir[i]<>#0) do
  498. begin
  499. { convert path name to DOS }
  500. if dir[i]='/' then
  501. dir[i]:='\';
  502. dir[0]:=chr(i);
  503. inc(i);
  504. end;
  505. { upcase the string }
  506. if drivenr<>0 then { Drive was supplied. We know it }
  507. dir[1]:=chr(65+drivenr-1)
  508. else
  509. begin
  510. { We need to get the current drive from DOS function 19H }
  511. { because the drive was the default, which can be unknown }
  512. asm
  513. movb $0x19,%ah
  514. int $0x21
  515. addb $65,%al
  516. movb %al,i
  517. end;
  518. dir[1]:=chr(i);
  519. end;
  520. dir:=upcase(dir);
  521. end;
  522. {*****************************************************************************
  523. System Dependent Exit code
  524. *****************************************************************************}
  525. Procedure system_exit;
  526. var
  527. err : byte;
  528. begin
  529. flush(stderr);
  530. err:=exitcode and $ff;
  531. asm
  532. movl $0x4c00,%eax
  533. movb err,%al
  534. int $0x21
  535. end;
  536. end;
  537. {*****************************************************************************
  538. SystemUnit Initialization
  539. *****************************************************************************}
  540. Begin
  541. {$ifdef SYSTEMDEBUG}
  542. { to test stack depth }
  543. loweststack:=maxlongint;
  544. {$endif}
  545. { Setup heap }
  546. InitHeap;
  547. { Setup stdin, stdout and stderr }
  548. OpenStdIO(Input,fmInput,StdInputHandle);
  549. OpenStdIO(Output,fmOutput,StdOutputHandle);
  550. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  551. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  552. { Reset IO Error }
  553. InOutRes:=0;
  554. End.
  555. {
  556. $Log$
  557. Revision 1.8 2001-07-29 13:50:44 peter
  558. * merged updates from v10
  559. Revision 1.7 2001/06/30 18:55:49 hajny
  560. * GetDir fix for inaccessible drives
  561. Revision 1.6 2001/06/19 20:46:07 hajny
  562. * platform specific constants moved after systemh.inc, BeOS omission corrected
  563. Revision 1.5 2001/06/13 22:22:59 hajny
  564. + platform specific information
  565. Revision 1.4 2001/03/21 21:08:20 hajny
  566. * GetDir fixed
  567. Revision 1.3 2001/03/10 09:57:51 hajny
  568. * FExpand without IOResult change, remaining direct asm removed
  569. Revision 1.2 2000/07/13 11:33:38 michael
  570. + removed logs
  571. }