system.pp 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 by 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. { no stack check in system }
  12. {$S-}
  13. unit system;
  14. {$I os.inc}
  15. interface
  16. { include system-independent routine headers }
  17. {$I systemh.inc}
  18. { include heap support headers }
  19. {$I heaph.inc}
  20. const
  21. { Default filehandles }
  22. UnusedHandle = $ffff;
  23. StdInputHandle = 0;
  24. StdOutputHandle = 1;
  25. StdErrorHandle = 2;
  26. { Default memory segments (Tp7 compatibility) }
  27. seg0040 = $0040;
  28. segA000 = $A000;
  29. segB000 = $B000;
  30. segB800 = $B800;
  31. var
  32. { Mem[] support }
  33. mem : array[0..$7fffffff] of byte absolute $0;
  34. memw : array[0..$7fffffff] of word absolute $0;
  35. meml : array[0..$7fffffff] of longint absolute $0;
  36. { C-compatible arguments and environment }
  37. argc : longint;
  38. argv : ppchar;
  39. envp : ppchar;
  40. dos_argv0 : pchar;
  41. {$ifndef RTLLITE}
  42. { System info }
  43. Win95 : boolean;
  44. {$endif RTLLITE}
  45. type
  46. { Dos Extender info }
  47. p_stub_info = ^t_stub_info;
  48. t_stub_info = packed record
  49. magic : array[0..15] of char;
  50. size : longint;
  51. minstack : longint;
  52. memory_handle : longint;
  53. initial_size : longint;
  54. minkeep : word;
  55. ds_selector : word;
  56. ds_segment : word;
  57. psp_selector : word;
  58. cs_selector : word;
  59. env_size : word;
  60. basename : array[0..7] of char;
  61. argv0 : array [0..15] of char;
  62. dpmi_server : array [0..15] of char;
  63. end;
  64. p_go32_info_block = ^t_go32_info_block;
  65. t_go32_info_block = packed record
  66. size_of_this_structure_in_bytes : longint; {offset 0}
  67. linear_address_of_primary_screen : longint; {offset 4}
  68. linear_address_of_secondary_screen : longint; {offset 8}
  69. linear_address_of_transfer_buffer : longint; {offset 12}
  70. size_of_transfer_buffer : longint; {offset 16}
  71. pid : longint; {offset 20}
  72. master_interrupt_controller_base : byte; {offset 24}
  73. slave_interrupt_controller_base : byte; {offset 25}
  74. selector_for_linear_memory : word; {offset 26}
  75. linear_address_of_stub_info_structure : longint; {offset 28}
  76. linear_address_of_original_psp : longint; {offset 32}
  77. run_mode : word; {offset 36}
  78. run_mode_info : word; {offset 38}
  79. end;
  80. var
  81. stub_info : p_stub_info;
  82. go32_info_block : t_go32_info_block;
  83. {
  84. necessary for objects.pas, should be removed (at least from the interface
  85. to the implementation)
  86. }
  87. type
  88. trealregs=record
  89. realedi,realesi,realebp,realres,
  90. realebx,realedx,realecx,realeax : longint;
  91. realflags,
  92. reales,realds,realfs,realgs,
  93. realip,realcs,realsp,realss : word;
  94. end;
  95. function do_write(h,addr,len : longint) : longint;
  96. function do_read(h,addr,len : longint) : longint;
  97. procedure syscopyfromdos(addr : longint; len : longint);
  98. procedure syscopytodos(addr : longint; len : longint);
  99. procedure sysrealintr(intnr : word;var regs : trealregs);
  100. function tb : longint;
  101. implementation
  102. { include system independent routines }
  103. {$I system.inc}
  104. const
  105. carryflag = 1;
  106. var
  107. doscmd : string[128]; { Dos commandline copied from PSP, max is 128 chars }
  108. {$ASMMODE DIRECT}
  109. procedure halt(errnum : byte);
  110. begin
  111. do_exit;
  112. flush(stderr);
  113. asm
  114. movzbw errnum,%ax
  115. pushw %ax
  116. call ___exit {frees all dpmi memory !!}
  117. end;
  118. end;
  119. procedure int_stackcheck(stack_size:longint);[public,alias: 'STACKCHECK'];
  120. {
  121. called when trying to get local stack if the compiler directive $S
  122. is set this function must preserve esi !!!! because esi is set by
  123. the calling proc for methods it must preserve all registers !!
  124. With a 2048 byte safe area used to write to StdIo without crossing
  125. the stack boundary
  126. }
  127. begin
  128. asm
  129. pushl %eax
  130. pushl %ebx
  131. movl stack_size,%ebx
  132. addl $2048,%ebx
  133. movl %esp,%eax
  134. subl %ebx,%eax
  135. {$ifdef SYSTEMDEBUG}
  136. movl U_SYSTEM_LOWESTSTACK,%ebx
  137. cmpl %eax,%ebx
  138. jb .L_is_not_lowest
  139. movl %eax,U_SYSTEM_LOWESTSTACK
  140. .L_is_not_lowest:
  141. {$endif SYSTEMDEBUG}
  142. movl __stkbottom,%ebx
  143. cmpl %eax,%ebx
  144. jae .L__short_on_stack
  145. popl %ebx
  146. popl %eax
  147. leave
  148. ret $4
  149. .L__short_on_stack:
  150. { can be usefull for error recovery !! }
  151. popl %ebx
  152. popl %eax
  153. end['EAX','EBX'];
  154. HandleError(202);
  155. end;
  156. function far_strlen(selector : word;linear_address : longint) : longint;
  157. begin
  158. asm
  159. movl linear_address,%edx
  160. movl %edx,%ecx
  161. movw selector,%gs
  162. .Larg19:
  163. movb %gs:(%edx),%al
  164. testb %al,%al
  165. je .Larg20
  166. incl %edx
  167. jmp .Larg19
  168. .Larg20:
  169. movl %edx,%eax
  170. subl %ecx,%eax
  171. movl %eax,__RESULT
  172. end;
  173. end;
  174. {$ASMMODE ATT}
  175. function tb : longint;
  176. begin
  177. tb:=go32_info_block.linear_address_of_transfer_buffer;
  178. end;
  179. function tb_size : longint;
  180. begin
  181. tb_size:=go32_info_block.size_of_transfer_buffer;
  182. end;
  183. function dos_selector : word;
  184. begin
  185. dos_selector:=go32_info_block.selector_for_linear_memory;
  186. end;
  187. function get_ds : word;assembler;
  188. asm
  189. movw %ds,%ax
  190. end;
  191. procedure sysseg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  192. begin
  193. if count=0 then
  194. exit;
  195. if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  196. asm
  197. pushw %es
  198. pushw %ds
  199. cld
  200. movl count,%ecx
  201. movl source,%esi
  202. movl dest,%edi
  203. movw dseg,%ax
  204. movw %ax,%es
  205. movw sseg,%ax
  206. movw %ax,%ds
  207. movl %ecx,%eax
  208. shrl $2,%ecx
  209. rep
  210. movsl
  211. movl %eax,%ecx
  212. andl $3,%ecx
  213. rep
  214. movsb
  215. popw %ds
  216. popw %es
  217. end ['ESI','EDI','ECX','EAX']
  218. else if (source<dest) then
  219. { copy backward for overlapping }
  220. asm
  221. pushw %es
  222. pushw %ds
  223. std
  224. movl count,%ecx
  225. movl source,%esi
  226. movl dest,%edi
  227. movw dseg,%ax
  228. movw %ax,%es
  229. movw sseg,%ax
  230. movw %ax,%ds
  231. addl %ecx,%esi
  232. addl %ecx,%edi
  233. movl %ecx,%eax
  234. andl $3,%ecx
  235. orl %ecx,%ecx
  236. jz .LSEG_MOVE1
  237. { calculate esi and edi}
  238. decl %esi
  239. decl %edi
  240. rep
  241. movsb
  242. incl %esi
  243. incl %edi
  244. .LSEG_MOVE1:
  245. subl $4,%esi
  246. subl $4,%edi
  247. movl %eax,%ecx
  248. shrl $2,%ecx
  249. rep
  250. movsl
  251. cld
  252. popw %ds
  253. popw %es
  254. end ['ESI','EDI','ECX'];
  255. end;
  256. function atohex(s : pchar) : longint;
  257. var rv : longint;
  258. v : byte;
  259. begin
  260. rv := 0;
  261. while (s^ <>#0) do
  262. begin
  263. v := byte(s^) - byte('0');
  264. if (v > 9) then v := v - 7;
  265. v := v and 15; { in case it's lower case }
  266. rv := rv*16 + v;
  267. inc(longint(s));
  268. end;
  269. atohex := rv;
  270. end;
  271. procedure setup_arguments;
  272. type arrayword = array [0..0] of word;
  273. var psp : word;
  274. i,j : byte;
  275. quote : char;
  276. proxy_s : string[7];
  277. tempargv : ppchar;
  278. al,proxy_argc,proxy_seg,proxy_ofs,lin : longint;
  279. largs : array[0..127] of pchar;
  280. rm_argv : ^arrayword;
  281. begin
  282. for i := 1 to 127 do
  283. largs[i] := nil;
  284. psp:=stub_info^.psp_selector;
  285. largs[0]:=dos_argv0;
  286. argc := 1;
  287. sysseg_move(psp, 128, get_ds, longint(@doscmd), 128);
  288. {$IfDef SYSTEMDEBUG}
  289. Writeln('Dos command line is #',doscmd,'# size = ',length(doscmd));
  290. {$EndIf SYSTEMDEBUG}
  291. j := 1;
  292. quote := #0;
  293. for i:=1 to length(doscmd) do
  294. Begin
  295. if doscmd[i] = quote then
  296. begin
  297. quote := #0;
  298. doscmd[i] := #0;
  299. largs[argc]:=@doscmd[j];
  300. inc(argc);
  301. j := i+1;
  302. end else
  303. if (quote = #0) and ((doscmd[i] = '''') or (doscmd[i]='"')) then
  304. begin
  305. quote := doscmd[i];
  306. j := i + 1;
  307. end else
  308. if (quote = #0) and ((doscmd[i] = ' ')
  309. or (doscmd[i] = #9) or (doscmd[i] = #10) or
  310. (doscmd[i] = #12) or (doscmd[i] = #9)) then
  311. begin
  312. doscmd[i]:=#0;
  313. if j<i then
  314. begin
  315. largs[argc]:=@doscmd[j];
  316. inc(argc);
  317. j := i+1;
  318. end else inc(j);
  319. end else
  320. if (i = length(doscmd)) then
  321. begin
  322. doscmd[i+1]:=#0;
  323. largs[argc]:=@doscmd[j];
  324. inc(argc);
  325. end;
  326. end;
  327. if (argc > 1) and (far_strlen(get_ds,longint(largs[1])) = 6) then
  328. begin
  329. move(largs[1]^,proxy_s[1],6);
  330. proxy_s[0] := #6;
  331. if (proxy_s = '!proxy') then
  332. begin
  333. {$IfDef SYSTEMDEBUG}
  334. Writeln('proxy command line ');
  335. {$EndIf SYSTEMDEBUG}
  336. proxy_argc := atohex(largs[2]);
  337. proxy_seg := atohex(largs[3]);
  338. proxy_ofs := atohex(largs[4]);
  339. getmem(rm_argv,proxy_argc*sizeof(word));
  340. sysseg_move(dos_selector,proxy_seg*16+proxy_ofs, get_ds,longint(rm_argv),proxy_argc*sizeof(word));
  341. for i:=0 to proxy_argc - 1 do
  342. begin
  343. lin := proxy_seg*16 + rm_argv^[i];
  344. al :=far_strlen(dos_selector, lin);
  345. getmem(largs[i],al+1);
  346. sysseg_move(dos_selector, lin, get_ds,longint(largs[i]), al+1);
  347. {$IfDef SYSTEMDEBUG}
  348. Writeln('arg ',i,' #',largs[i],'#');
  349. {$EndIf SYSTEMDEBUG}
  350. end;
  351. argc := proxy_argc;
  352. end;
  353. end;
  354. getmem(argv,argc shl 2);
  355. for i := 0 to argc-1 do
  356. argv[i] := largs[i];
  357. tempargv:=argv;
  358. {$ASMMODE DIRECT}
  359. asm
  360. movl tempargv,%eax
  361. movl %eax,_args
  362. end;
  363. {$ASMMODE ATT}
  364. end;
  365. function strcopy(dest,source : pchar) : pchar;
  366. begin
  367. asm
  368. cld
  369. movl 12(%ebp),%edi
  370. movl $0xffffffff,%ecx
  371. xorb %al,%al
  372. repne
  373. scasb
  374. not %ecx
  375. movl 8(%ebp),%edi
  376. movl 12(%ebp),%esi
  377. movl %ecx,%eax
  378. shrl $2,%ecx
  379. rep
  380. movsl
  381. movl %eax,%ecx
  382. andl $3,%ecx
  383. rep
  384. movsb
  385. movl 8(%ebp),%eax
  386. leave
  387. ret $8
  388. end;
  389. end;
  390. procedure setup_environment;
  391. var env_selector : word;
  392. env_count : longint;
  393. dos_env,cp : pchar;
  394. stubaddr : p_stub_info;
  395. begin
  396. {$ASMMODE DIRECT}
  397. asm
  398. movl __stubinfo,%eax
  399. movl %eax,stubaddr
  400. end;
  401. {$ASMMODE ATT}
  402. stub_info:=stubaddr;
  403. getmem(dos_env,stub_info^.env_size);
  404. env_count:=0;
  405. sysseg_move(stub_info^.psp_selector,$2c, get_ds, longint(@env_selector), 2);
  406. sysseg_move(env_selector, 0, get_ds, longint(dos_env), stub_info^.env_size);
  407. cp:=dos_env;
  408. while cp ^ <> #0 do
  409. begin
  410. inc(env_count);
  411. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  412. inc(longint(cp)); { skip to next character }
  413. end;
  414. getmem(envp,(env_count+1) * sizeof(pchar));
  415. if (envp = nil) then exit;
  416. cp:=dos_env;
  417. env_count:=0;
  418. while cp^ <> #0 do
  419. begin
  420. getmem(envp[env_count],strlen(cp)+1);
  421. strcopy(envp[env_count], cp);
  422. {$IfDef SYSTEMDEBUG}
  423. Writeln('env ',env_count,' = "',envp[env_count],'"');
  424. {$EndIf SYSTEMDEBUG}
  425. inc(env_count);
  426. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  427. inc(longint(cp)); { skip to next character }
  428. end;
  429. envp[env_count]:=nil;
  430. longint(cp):=longint(cp)+3;
  431. getmem(dos_argv0,strlen(cp)+1);
  432. if (dos_argv0 = nil) then halt;
  433. strcopy(dos_argv0, cp);
  434. { update ___dos_argv0 also }
  435. {$ASMMODE DIRECT}
  436. asm
  437. movl U_SYSTEM_DOS_ARGV0,%eax
  438. movl %eax,___dos_argv0
  439. end;
  440. {$ASMMODE ATT}
  441. end;
  442. procedure syscopytodos(addr : longint; len : longint);
  443. begin
  444. if len > tb_size then HandleError(217);
  445. sysseg_move(get_ds,addr,dos_selector,tb,len);
  446. end;
  447. procedure syscopyfromdos(addr : longint; len : longint);
  448. begin
  449. if len > tb_size then HandleError(217);
  450. sysseg_move(dos_selector,tb,get_ds,addr,len);
  451. end;
  452. procedure sysrealintr(intnr : word;var regs : trealregs);
  453. begin
  454. regs.realsp:=0;
  455. regs.realss:=0;
  456. asm
  457. movw intnr,%bx
  458. xorl %ecx,%ecx
  459. movl regs,%edi
  460. movw $0x300,%ax
  461. int $0x31
  462. end;
  463. end;
  464. function paramcount : longint;
  465. begin
  466. paramcount := argc - 1;
  467. end;
  468. function paramstr(l : longint) : string;
  469. begin
  470. if (l>=0) and (l+1<=argc) then
  471. paramstr:=strpas(argv[l])
  472. else
  473. paramstr:='';
  474. end;
  475. procedure randomize;
  476. var
  477. hl : longint;
  478. regs : trealregs;
  479. begin
  480. regs.realeax:=$2c00;
  481. sysrealintr($21,regs);
  482. hl:=regs.realedx and $ffff;
  483. randseed:=hl*$10000+ (regs.realecx and $ffff);
  484. end;
  485. {*****************************************************************************
  486. Heap Management
  487. *****************************************************************************}
  488. {$ASMMODE DIRECT}
  489. function Sbrk(size : longint):longint;assembler;
  490. asm
  491. movl size,%eax
  492. pushl %eax
  493. call ___sbrk
  494. addl $4,%esp
  495. end;
  496. {$ASMMODE ATT}
  497. { include standard heap management }
  498. {$I heap.inc}
  499. {****************************************************************************
  500. Low level File Routines
  501. ****************************************************************************}
  502. procedure AllowSlash(p:pchar);
  503. var
  504. i : longint;
  505. begin
  506. { allow slash as backslash }
  507. for i:=0 to strlen(p) do
  508. if p[i]='/' then p[i]:='\';
  509. end;
  510. {$ifdef SYSTEMDEBUG}
  511. { Keep Track of open files }
  512. const
  513. max_files = 50;
  514. var
  515. opennames : array [0..max_files-1] of pchar;
  516. openfiles : array [0..max_files-1] of boolean;
  517. {$endif SYSTEMDEBUG}
  518. procedure do_close(handle : longint);
  519. var
  520. regs : trealregs;
  521. begin
  522. regs.realebx:=handle;
  523. {$ifdef SYSTEMDEBUG}
  524. if handle<max_files then
  525. openfiles[handle]:=false;
  526. {$endif SYSTEMDEBUG}
  527. regs.realeax:=$3e00;
  528. sysrealintr($21,regs);
  529. end;
  530. procedure do_erase(p : pchar);
  531. var
  532. regs : trealregs;
  533. begin
  534. AllowSlash(p);
  535. syscopytodos(longint(p),strlen(p)+1);
  536. regs.realedx:=tb and 15;
  537. regs.realds:=tb shr 4;
  538. {$ifndef RTLLITE}
  539. if Win95 then
  540. regs.realeax:=$7141
  541. else
  542. {$endif RTLLITE}
  543. regs.realeax:=$4100;
  544. regs.realesi:=0;
  545. regs.realecx:=0;
  546. sysrealintr($21,regs);
  547. if (regs.realflags and carryflag) <> 0 then
  548. InOutRes:=lo(regs.realeax);
  549. end;
  550. procedure do_rename(p1,p2 : pchar);
  551. var
  552. regs : trealregs;
  553. begin
  554. AllowSlash(p1);
  555. AllowSlash(p2);
  556. if strlen(p1)+strlen(p2)+3>tb_size then
  557. HandleError(217);
  558. sysseg_move(get_ds,longint(p2),dos_selector,tb,strlen(p2)+1);
  559. sysseg_move(get_ds,longint(p1),dos_selector,tb+strlen(p2)+2,strlen(p1)+1);
  560. regs.realedi:=tb and 15;
  561. regs.realedx:=tb and 15 + strlen(p2)+2;
  562. regs.realds:=tb shr 4;
  563. regs.reales:=regs.realds;
  564. {$ifndef RTLLITE}
  565. if Win95 then
  566. regs.realeax:=$7156
  567. else
  568. {$endif RTLLITE}
  569. regs.realeax:=$5600;
  570. regs.realecx:=$ff; { attribute problem here ! }
  571. sysrealintr($21,regs);
  572. if (regs.realflags and carryflag) <> 0 then
  573. InOutRes:=lo(regs.realeax);
  574. end;
  575. function do_write(h,addr,len : longint) : longint;
  576. var
  577. regs : trealregs;
  578. size,
  579. writesize : longint;
  580. begin
  581. writesize:=0;
  582. while len > 0 do
  583. begin
  584. if len>tb_size then
  585. size:=tb_size
  586. else
  587. size:=len;
  588. syscopytodos(addr+writesize,size);
  589. regs.realecx:=size;
  590. regs.realedx:=tb and 15;
  591. regs.realds:=tb shr 4;
  592. regs.realebx:=h;
  593. regs.realeax:=$4000;
  594. sysrealintr($21,regs);
  595. if (regs.realflags and carryflag) <> 0 then
  596. begin
  597. InOutRes:=lo(regs.realeax);
  598. exit(writesize);
  599. end;
  600. len:=len-size;
  601. writesize:=writesize+size;
  602. end;
  603. Do_Write:=WriteSize
  604. end;
  605. function do_read(h,addr,len : longint) : longint;
  606. var
  607. regs : trealregs;
  608. size,
  609. readsize : longint;
  610. begin
  611. readsize:=0;
  612. while len > 0 do
  613. begin
  614. if len>tb_size then
  615. size:=tb_size
  616. else
  617. size:=len;
  618. regs.realecx:=size;
  619. regs.realedx:=tb and 15;
  620. regs.realds:=tb shr 4;
  621. regs.realebx:=h;
  622. regs.realeax:=$3f00;
  623. sysrealintr($21,regs);
  624. if (regs.realflags and carryflag) <> 0 then
  625. begin
  626. InOutRes:=lo(regs.realeax);
  627. do_read:=0;
  628. exit;
  629. end
  630. else
  631. if regs.realeax<size then
  632. begin
  633. syscopyfromdos(addr+readsize,regs.realeax);
  634. do_read:=readsize+regs.realeax;
  635. exit;
  636. end;
  637. syscopyfromdos(addr+readsize,regs.realeax);
  638. readsize:=readsize+regs.realeax;
  639. len:=len-regs.realeax;
  640. end;
  641. do_read:=readsize;
  642. end;
  643. function do_filepos(handle : longint) : longint;
  644. var
  645. regs : trealregs;
  646. begin
  647. regs.realebx:=handle;
  648. regs.realecx:=0;
  649. regs.realedx:=0;
  650. regs.realeax:=$4201;
  651. sysrealintr($21,regs);
  652. if (regs.realflags and carryflag) <> 0 then
  653. Begin
  654. InOutRes:=lo(regs.realeax);
  655. do_filepos:=0;
  656. end
  657. else
  658. do_filepos:=lo(regs.realedx) shl 16+lo(regs.realeax);
  659. end;
  660. procedure do_seek(handle,pos : longint);
  661. var
  662. regs : trealregs;
  663. begin
  664. regs.realebx:=handle;
  665. regs.realecx:=pos shr 16;
  666. regs.realedx:=pos and $ffff;
  667. regs.realeax:=$4200;
  668. sysrealintr($21,regs);
  669. if (regs.realflags and carryflag) <> 0 then
  670. InOutRes:=lo(regs.realeax);
  671. end;
  672. function do_seekend(handle:longint):longint;
  673. var
  674. regs : trealregs;
  675. begin
  676. regs.realebx:=handle;
  677. regs.realecx:=0;
  678. regs.realedx:=0;
  679. regs.realeax:=$4202;
  680. sysrealintr($21,regs);
  681. if (regs.realflags and carryflag) <> 0 then
  682. Begin
  683. InOutRes:=lo(regs.realeax);
  684. do_seekend:=0;
  685. end
  686. else
  687. do_seekend:=lo(regs.realedx) shl 16+lo(regs.realeax);
  688. end;
  689. function do_filesize(handle : longint) : longint;
  690. var
  691. aktfilepos : longint;
  692. begin
  693. aktfilepos:=do_filepos(handle);
  694. do_filesize:=do_seekend(handle);
  695. do_seek(handle,aktfilepos);
  696. end;
  697. { truncate at a given position }
  698. procedure do_truncate (handle,pos:longint);
  699. var
  700. regs : trealregs;
  701. begin
  702. do_seek(handle,pos);
  703. regs.realecx:=0;
  704. regs.realedx:=tb and 15;
  705. regs.realds:=tb shr 4;
  706. regs.realebx:=handle;
  707. regs.realeax:=$4000;
  708. sysrealintr($21,regs);
  709. if (regs.realflags and carryflag) <> 0 then
  710. InOutRes:=lo(regs.realeax);
  711. end;
  712. procedure do_open(var f;p:pchar;flags:longint);
  713. {
  714. filerec and textrec have both handle and mode as the first items so
  715. they could use the same routine for opening/creating.
  716. when (flags and $10) the file will be append
  717. when (flags and $100) the file will be truncate/rewritten
  718. when (flags and $1000) there is no check for close (needed for textfiles)
  719. }
  720. var
  721. regs : trealregs;
  722. action : longint;
  723. begin
  724. AllowSlash(p);
  725. { close first if opened }
  726. if ((flags and $1000)=0) then
  727. begin
  728. case filerec(f).mode of
  729. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  730. fmclosed : ;
  731. else
  732. begin
  733. inoutres:=102; {not assigned}
  734. exit;
  735. end;
  736. end;
  737. end;
  738. { reset file handle }
  739. filerec(f).handle:=UnusedHandle;
  740. action:=$1;
  741. { convert filemode to filerec modes }
  742. case (flags and 3) of
  743. 0 : filerec(f).mode:=fminput;
  744. 1 : filerec(f).mode:=fmoutput;
  745. 2 : filerec(f).mode:=fminout;
  746. end;
  747. if (flags and $100)<>0 then
  748. begin
  749. filerec(f).mode:=fmoutput;
  750. action:=$12; {create file function}
  751. end;
  752. { empty name is special }
  753. if p[0]=#0 then
  754. begin
  755. case filerec(f).mode of
  756. fminput : filerec(f).handle:=StdInputHandle;
  757. fmappend,
  758. fmoutput : begin
  759. filerec(f).handle:=StdOutputHandle;
  760. filerec(f).mode:=fmoutput; {fool fmappend}
  761. end;
  762. end;
  763. exit;
  764. end;
  765. { real dos call }
  766. syscopytodos(longint(p),strlen(p)+1);
  767. {$ifndef RTLLITE}
  768. if Win95 then
  769. regs.realeax:=$716c
  770. else
  771. {$endif RTLLITE}
  772. regs.realeax:=$6c00;
  773. regs.realedx:=action;
  774. regs.realds:=tb shr 4;
  775. regs.realesi:=tb and 15;
  776. regs.realebx:=$2000+(flags and $ff);
  777. regs.realecx:=$20;
  778. sysrealintr($21,regs);
  779. if (regs.realflags and carryflag) <> 0 then
  780. begin
  781. InOutRes:=lo(regs.realeax);
  782. exit;
  783. end
  784. else
  785. filerec(f).handle:=regs.realeax;
  786. {$ifdef SYSTEMDEBUG}
  787. if regs.realeax<max_files then
  788. begin
  789. openfiles[regs.realeax]:=true;
  790. getmem(opennames[regs.realeax],strlen(p)+1);
  791. opennames[regs.realeax]:=p;
  792. end;
  793. {$endif SYSTEMDEBUG}
  794. { append mode }
  795. if (flags and $10)<>0 then
  796. begin
  797. do_seekend(filerec(f).handle);
  798. filerec(f).mode:=fmoutput; {fool fmappend}
  799. end;
  800. end;
  801. function do_isdevice(handle:longint):boolean;
  802. var
  803. regs : trealregs;
  804. begin
  805. regs.realebx:=handle;
  806. regs.realeax:=$4400;
  807. sysrealintr($21,regs);
  808. do_isdevice:=(regs.realedx and $80)<>0;
  809. if (regs.realflags and carryflag) <> 0 then
  810. InOutRes:=lo(regs.realeax);
  811. end;
  812. {*****************************************************************************
  813. UnTyped File Handling
  814. *****************************************************************************}
  815. {$i file.inc}
  816. {*****************************************************************************
  817. Typed File Handling
  818. *****************************************************************************}
  819. {$i typefile.inc}
  820. {*****************************************************************************
  821. Text File Handling
  822. *****************************************************************************}
  823. {$DEFINE EOF_CTRLZ}
  824. {$i text.inc}
  825. {*****************************************************************************
  826. Directory Handling
  827. *****************************************************************************}
  828. procedure DosDir(func:byte;const s:string);
  829. var
  830. buffer : array[0..255] of char;
  831. regs : trealregs;
  832. begin
  833. move(s[1],buffer,length(s));
  834. buffer[length(s)]:=#0;
  835. AllowSlash(pchar(@buffer));
  836. syscopytodos(longint(@buffer),length(s)+1);
  837. regs.realedx:=tb and 15;
  838. regs.realds:=tb shr 4;
  839. {$ifndef RTLLITE}
  840. if Win95 then
  841. regs.realeax:=$7100+func
  842. else
  843. {$endif RTLLITE}
  844. regs.realeax:=func shl 8;
  845. sysrealintr($21,regs);
  846. if (regs.realflags and carryflag) <> 0 then
  847. InOutRes:=lo(regs.realeax);
  848. end;
  849. procedure mkdir(const s : string);[IOCheck];
  850. begin
  851. If InOutRes <> 0 then exit;
  852. DosDir($39,s);
  853. end;
  854. procedure rmdir(const s : string);[IOCheck];
  855. begin
  856. If InOutRes <> 0 then exit;
  857. DosDir($3a,s);
  858. end;
  859. procedure chdir(const s : string);[IOCheck];
  860. begin
  861. If InOutRes <> 0 then exit;
  862. DosDir($3b,s);
  863. end;
  864. procedure getdir(drivenr : byte;var dir : string);
  865. var
  866. temp : array[0..255] of char;
  867. i : longint;
  868. regs : trealregs;
  869. begin
  870. regs.realedx:=drivenr;
  871. regs.realesi:=tb and 15;
  872. regs.realds:=tb shr 4;
  873. {$ifndef RTLLITE}
  874. if Win95 then
  875. regs.realeax:=$7147
  876. else
  877. {$endif RTLLITE}
  878. regs.realeax:=$4700;
  879. sysrealintr($21,regs);
  880. if (regs.realflags and carryflag) <> 0 then
  881. Begin
  882. InOutRes:=lo(regs.realeax);
  883. exit;
  884. end
  885. else
  886. syscopyfromdos(longint(@temp),251);
  887. { conversation to Pascal string including slash conversion }
  888. i:=0;
  889. while (temp[i]<>#0) do
  890. begin
  891. if temp[i]='/' then
  892. temp[i]:='\';
  893. dir[i+4]:=temp[i];
  894. inc(i);
  895. end;
  896. dir[2]:=':';
  897. dir[3]:='\';
  898. dir[0]:=char(i+3);
  899. { upcase the string }
  900. dir:=upcase(dir);
  901. if drivenr<>0 then { Drive was supplied. We know it }
  902. dir[1]:=char(65+drivenr-1)
  903. else
  904. begin
  905. { We need to get the current drive from DOS function 19H }
  906. { because the drive was the default, which can be unknown }
  907. regs.realeax:=$1900;
  908. sysrealintr($21,regs);
  909. i:= (regs.realeax and $ff) + ord('A');
  910. dir[1]:=chr(i);
  911. end;
  912. end;
  913. {*****************************************************************************
  914. SystemUnit Initialization
  915. *****************************************************************************}
  916. {$ifndef RTLLITE}
  917. function CheckWin95:boolean;
  918. var
  919. regs : TRealRegs;
  920. begin
  921. regs.realeax:=$160a;
  922. sysrealintr($2f,regs);
  923. CheckWin95:=(regs.realeax=0) and ((regs.realebx and $ff00)=$400);
  924. end;
  925. {$endif RTLLITE}
  926. Begin
  927. { to test stack depth }
  928. loweststack:=maxlongint;
  929. { Setup heap }
  930. InitHeap;
  931. { Setup stdin, stdout and stderr }
  932. OpenStdIO(Input,fmInput,StdInputHandle);
  933. OpenStdIO(Output,fmOutput,StdOutputHandle);
  934. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  935. { Setup environment and arguments }
  936. Setup_Environment;
  937. Setup_Arguments;
  938. { Use Win95 LFN }
  939. Win95:=CheckWin95;
  940. { Reset IO Error }
  941. InOutRes:=0;
  942. End.
  943. {
  944. $Log$
  945. Revision 1.15 1998-08-19 10:56:34 pierre
  946. + added some special code for C interface
  947. to avoid loading of crt1.o or dpmiexcp.o from the libc.a
  948. Revision 1.14 1998/08/04 14:34:38 pierre
  949. * small bug fix to get it compiled with bugfix version !!
  950. (again the asmmode problem !!!
  951. Peter it was really not the best idea you had !!)
  952. Revision 1.13 1998/07/30 13:26:22 michael
  953. + Added support for ErrorProc variable. All internal functions are required
  954. to call HandleError instead of runerror from now on.
  955. This is necessary for exception support.
  956. Revision 1.12 1998/07/13 21:19:08 florian
  957. * some problems with ansi string support fixed
  958. Revision 1.11 1998/07/07 12:33:08 carl
  959. * added 2k buffer for stack checking for correct io on error
  960. Revision 1.10 1998/07/02 12:29:20 carl
  961. * IOCheck for rmdir,chdir and mkdir as in TP
  962. NOTE: I'm pretty SURE this will not compile and link correctly with FPC
  963. 0.99.5
  964. Revision 1.9 1998/07/01 15:29:57 peter
  965. * better readln/writeln
  966. Revision 1.8 1998/06/26 08:19:10 pierre
  967. + all debug in ifdef SYSTEMDEBUG
  968. + added local arrays :
  969. opennames names of opened files
  970. fileopen boolean array to know if still open
  971. usefull with gdb if you get problems about too
  972. many open files !!
  973. Revision 1.7 1998/06/15 15:17:08 daniel
  974. * RTLLITE conditional added to produce smaller RTL.
  975. Revision 1.6 1998/05/31 14:18:29 peter
  976. * force att or direct assembling
  977. * cleanup of some files
  978. Revision 1.5 1998/05/21 19:30:52 peter
  979. * objects compiles for linux
  980. + assign(pchar), assign(char), rename(pchar), rename(char)
  981. * fixed read_text_as_array
  982. + read_text_as_pchar which was not yet in the rtl
  983. Revision 1.4 1998/05/04 17:58:41 peter
  984. * fix for smartlinking with _ARGS
  985. Revision 1.3 1998/05/04 16:21:54 florian
  986. + win95 flag to the interface moved
  987. }