system.pp 24 KB

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