system.pp 16 KB

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