system.pp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  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 :
  377. FileRec(f).Handle:=StdInputHandle;
  378. fminout, { this is set by rewrite }
  379. fmoutput :
  380. FileRec(f).Handle:=StdOutputHandle;
  381. fmappend :
  382. begin
  383. FileRec(f).Handle:=StdOutputHandle;
  384. FileRec(f).mode:=fmoutput; {fool fmappend}
  385. end;
  386. end;
  387. exit;
  388. end;
  389. asm
  390. movl $0xff02,%eax
  391. movl oflags,%ecx
  392. movl p,%ebx
  393. int $0x21
  394. jnc .LOPEN1
  395. movw %ax,inoutres
  396. movw $0xffff,%ax
  397. .LOPEN1:
  398. movl f,%edx
  399. movw %ax,(%edx)
  400. end;
  401. if (flags and $100)<>0 then
  402. do_seekend(filerec(f).handle);
  403. end;
  404. function do_isdevice(handle : longint):boolean;assembler;
  405. asm
  406. movl $0x4400,%eax
  407. movl handle,%ebx
  408. pushl %ebp
  409. int $0x21
  410. popl %ebp
  411. jnc .LDOSDEVICE
  412. movw %ax,inoutres
  413. xorl %edx,%edx
  414. .LDOSDEVICE:
  415. movl %edx,%eax
  416. shrl $7,%eax
  417. andl $1,%eax
  418. end;
  419. {*****************************************************************************
  420. UnTyped File Handling
  421. *****************************************************************************}
  422. {$i file.inc}
  423. {*****************************************************************************
  424. Typed File Handling
  425. *****************************************************************************}
  426. {$i typefile.inc}
  427. {*****************************************************************************
  428. Text File Handling
  429. *****************************************************************************}
  430. {$DEFINE EOF_CTRLZ}
  431. {$i text.inc}
  432. {*****************************************************************************
  433. Directory Handling
  434. *****************************************************************************}
  435. procedure DosDir(func:byte;const s:string);
  436. var
  437. buffer : array[0..255] of char;
  438. begin
  439. move(s[1],buffer,length(s));
  440. buffer[length(s)]:=#0;
  441. AllowSlash(pchar(@buffer));
  442. asm
  443. leal buffer,%edx
  444. movb func,%ah
  445. int $0x21
  446. jnc .LDOS_DIRS1
  447. movw %ax,inoutres
  448. .LDOS_DIRS1:
  449. end;
  450. end;
  451. procedure mkdir(const s : string);[IOCheck];
  452. begin
  453. If InOutRes <> 0 then exit;
  454. DosDir($39,s);
  455. end;
  456. procedure rmdir(const s : string);[IOCheck];
  457. begin
  458. If InOutRes <> 0 then exit;
  459. DosDir($3a,s);
  460. end;
  461. procedure chdir(const s : string);[IOCheck];
  462. begin
  463. If InOutRes <> 0 then exit;
  464. DosDir($3b,s);
  465. end;
  466. procedure getdir(drivenr : byte;var dir : shortstring);
  467. var
  468. temp : array[0..255] of char;
  469. sof : pchar;
  470. i : byte;
  471. begin
  472. sof:=pchar(@dir[4]);
  473. { dir[1..3] will contain '[drivenr]:\', but is not supplied by DOS,
  474. so we let dos string start at dir[4]
  475. Get dir from drivenr : 0=default, 1=A etc }
  476. asm
  477. movb drivenr,%dl
  478. movl sof,%esi
  479. mov $0x47,%ah
  480. int $0x21
  481. end;
  482. { Now Dir should be filled with directory in ASCIIZ starting from dir[4] }
  483. dir[0]:=#3;
  484. dir[2]:=':';
  485. dir[3]:='\';
  486. i:=4;
  487. { conversation to Pascal string }
  488. while (dir[i]<>#0) do
  489. begin
  490. { convert path name to DOS }
  491. if dir[i]='/' then
  492. dir[i]:='\';
  493. dir[0]:=chr(i);
  494. inc(i);
  495. end;
  496. { upcase the string }
  497. dir:=upcase(dir);
  498. if drivenr<>0 then { Drive was supplied. We know it }
  499. dir[1]:=chr(65+drivenr-1)
  500. else
  501. begin
  502. { We need to get the current drive from DOS function 19H }
  503. { because the drive was the default, which can be unknown }
  504. asm
  505. movb $0x19,%ah
  506. int $0x21
  507. addb $65,%al
  508. movb %al,i
  509. end;
  510. dir[1]:=chr(i);
  511. end;
  512. end;
  513. {*****************************************************************************
  514. System Dependent Exit code
  515. *****************************************************************************}
  516. Procedure system_exit;
  517. begin
  518. end;
  519. {*****************************************************************************
  520. SystemUnit Initialization
  521. *****************************************************************************}
  522. Begin
  523. { to test stack depth }
  524. loweststack:=maxlongint;
  525. { Setup heap }
  526. InitHeap;
  527. { Setup stdin, stdout and stderr }
  528. OpenStdIO(Input,fmInput,StdInputHandle);
  529. OpenStdIO(Output,fmOutput,StdOutputHandle);
  530. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  531. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  532. { Reset IO Error }
  533. InOutRes:=0;
  534. End.
  535. {
  536. $Log$
  537. Revision 1.9 2000-01-20 23:38:02 peter
  538. * support fm_inout as stdoutput for assign(f,'');rewrite(f,1); becuase
  539. rewrite opens always with filemode 2
  540. Revision 1.8 2000/01/07 16:41:30 daniel
  541. * copyright 2000
  542. Revision 1.7 2000/01/07 16:32:23 daniel
  543. * copyright 2000 added
  544. Revision 1.6 1999/09/10 15:40:33 peter
  545. * fixed do_open flags to be > $100, becuase filemode can be upto 255
  546. Revision 1.5 1999/06/01 13:23:11 peter
  547. * fixes to work with the new makefile
  548. * os2 compiles now correct under linux
  549. Revision 1.4 1999/04/08 12:22:57 peter
  550. * removed os.inc
  551. Revision 1.3 1999/01/18 10:05:49 pierre
  552. + system_exit procedure added
  553. Revision 1.2 1998/12/28 15:50:44 peter
  554. + stdout, which is needed when you write something in the system unit
  555. to the screen. Like the runtime error
  556. Revision 1.1 1998/12/21 13:07:02 peter
  557. * use -FE
  558. Revision 1.12 1998/12/15 22:42:51 peter
  559. * removed temp symbols
  560. Revision 1.11 1998/11/29 22:28:09 peter
  561. + io-error 103 added
  562. Revision 1.10 1998/11/16 14:15:01 pierre
  563. * changed getdir(byte,string) to getdir(byte,shortstring)
  564. Revision 1.9 1998/09/14 10:48:03 peter
  565. * FPC_ names
  566. * Heap manager is now system independent
  567. Revision 1.8 1998/07/30 13:28:33 michael
  568. + Added support for errorproc. Changed runerror to HandleError
  569. Revision 1.7 1998/07/07 12:30:20 carl
  570. * 2k buffer for stack shecking to permimt correct io
  571. Revision 1.6 1998/07/02 12:26:55 carl
  572. * do_open was WRONG! Fixed!
  573. * do_isdevice small fix with ATT parser
  574. * I386_ATT put back , otherwise would NOT link!
  575. * IoCheck for rmdir,chdir,mkdir
  576. Revision 1.5 1998/07/01 15:29:56 peter
  577. * better readln/writeln
  578. Revision 1.4 1998/05/31 14:18:19 peter
  579. * force att or direct assembling
  580. * cleanup of some files
  581. Revision 1.3 1998/05/22 00:39:33 peter
  582. * go32v1, go32v2 recompiles with the new objects
  583. * remake3 works again with go32v2
  584. - removed some "optimizes" from daniel which were wrong
  585. }