system.pp 26 KB

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