2
0

system.pp 24 KB

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