2
0

system.pp 25 KB

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