system.pp 15 KB

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