system.pp 24 KB

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