system.pp 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157
  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. LFNSupport : 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_segment : longint;
  180. begin
  181. tb_segment:=go32_info_block.linear_address_of_transfer_buffer shr 4;
  182. end;
  183. function tb_offset : longint;
  184. begin
  185. tb_offset:=go32_info_block.linear_address_of_transfer_buffer and $f;
  186. end;
  187. function tb_size : longint;
  188. begin
  189. tb_size:=go32_info_block.size_of_transfer_buffer;
  190. end;
  191. function dos_selector : word;
  192. begin
  193. dos_selector:=go32_info_block.selector_for_linear_memory;
  194. end;
  195. function get_ds : word;assembler;
  196. asm
  197. movw %ds,%ax
  198. end;
  199. procedure sysseg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  200. begin
  201. if count=0 then
  202. exit;
  203. if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  204. asm
  205. pushw %es
  206. pushw %ds
  207. cld
  208. movl count,%ecx
  209. movl source,%esi
  210. movl dest,%edi
  211. movw dseg,%ax
  212. movw %ax,%es
  213. movw sseg,%ax
  214. movw %ax,%ds
  215. movl %ecx,%eax
  216. shrl $2,%ecx
  217. rep
  218. movsl
  219. movl %eax,%ecx
  220. andl $3,%ecx
  221. rep
  222. movsb
  223. popw %ds
  224. popw %es
  225. end ['ESI','EDI','ECX','EAX']
  226. else if (source<dest) then
  227. { copy backward for overlapping }
  228. asm
  229. pushw %es
  230. pushw %ds
  231. std
  232. movl count,%ecx
  233. movl source,%esi
  234. movl dest,%edi
  235. movw dseg,%ax
  236. movw %ax,%es
  237. movw sseg,%ax
  238. movw %ax,%ds
  239. addl %ecx,%esi
  240. addl %ecx,%edi
  241. movl %ecx,%eax
  242. andl $3,%ecx
  243. orl %ecx,%ecx
  244. jz .LSEG_MOVE1
  245. { calculate esi and edi}
  246. decl %esi
  247. decl %edi
  248. rep
  249. movsb
  250. incl %esi
  251. incl %edi
  252. .LSEG_MOVE1:
  253. subl $4,%esi
  254. subl $4,%edi
  255. movl %eax,%ecx
  256. shrl $2,%ecx
  257. rep
  258. movsl
  259. cld
  260. popw %ds
  261. popw %es
  262. end ['ESI','EDI','ECX'];
  263. end;
  264. function atohex(s : pchar) : longint;
  265. var rv : longint;
  266. v : byte;
  267. begin
  268. rv := 0;
  269. while (s^ <>#0) do
  270. begin
  271. v := byte(s^) - byte('0');
  272. if (v > 9) then v := v - 7;
  273. v := v and 15; { in case it's lower case }
  274. rv := rv*16 + v;
  275. inc(longint(s));
  276. end;
  277. atohex := rv;
  278. end;
  279. procedure setup_arguments;
  280. type arrayword = array [0..0] of word;
  281. var psp : word;
  282. i,j : byte;
  283. quote : char;
  284. proxy_s : string[7];
  285. tempargv : ppchar;
  286. al,proxy_argc,proxy_seg,proxy_ofs,lin : longint;
  287. largs : array[0..127] of pchar;
  288. rm_argv : ^arrayword;
  289. begin
  290. for i := 1 to 127 do
  291. largs[i] := nil;
  292. psp:=stub_info^.psp_selector;
  293. largs[0]:=dos_argv0;
  294. argc := 1;
  295. sysseg_move(psp, 128, get_ds, longint(@doscmd), 128);
  296. {$IfDef SYSTEMDEBUG}
  297. Writeln('Dos command line is #',doscmd,'# size = ',length(doscmd));
  298. {$EndIf SYSTEMDEBUG}
  299. j := 1;
  300. quote := #0;
  301. for i:=1 to length(doscmd) do
  302. Begin
  303. if doscmd[i] = quote then
  304. begin
  305. quote := #0;
  306. doscmd[i] := #0;
  307. largs[argc]:=@doscmd[j];
  308. inc(argc);
  309. j := i+1;
  310. end else
  311. if (quote = #0) and ((doscmd[i] = '''') or (doscmd[i]='"')) then
  312. begin
  313. quote := doscmd[i];
  314. j := i + 1;
  315. end else
  316. if (quote = #0) and ((doscmd[i] = ' ')
  317. or (doscmd[i] = #9) or (doscmd[i] = #10) or
  318. (doscmd[i] = #12) or (doscmd[i] = #9)) then
  319. begin
  320. doscmd[i]:=#0;
  321. if j<i then
  322. begin
  323. largs[argc]:=@doscmd[j];
  324. inc(argc);
  325. j := i+1;
  326. end else inc(j);
  327. end else
  328. if (i = length(doscmd)) then
  329. begin
  330. doscmd[i+1]:=#0;
  331. largs[argc]:=@doscmd[j];
  332. inc(argc);
  333. end;
  334. end;
  335. if (argc > 1) and (far_strlen(get_ds,longint(largs[1])) = 6) then
  336. begin
  337. move(largs[1]^,proxy_s[1],6);
  338. proxy_s[0] := #6;
  339. if (proxy_s = '!proxy') then
  340. begin
  341. {$IfDef SYSTEMDEBUG}
  342. Writeln('proxy command line ');
  343. {$EndIf SYSTEMDEBUG}
  344. proxy_argc := atohex(largs[2]);
  345. proxy_seg := atohex(largs[3]);
  346. proxy_ofs := atohex(largs[4]);
  347. getmem(rm_argv,proxy_argc*sizeof(word));
  348. sysseg_move(dos_selector,proxy_seg*16+proxy_ofs, get_ds,longint(rm_argv),proxy_argc*sizeof(word));
  349. for i:=0 to proxy_argc - 1 do
  350. begin
  351. lin := proxy_seg*16 + rm_argv^[i];
  352. al :=far_strlen(dos_selector, lin);
  353. getmem(largs[i],al+1);
  354. sysseg_move(dos_selector, lin, get_ds,longint(largs[i]), al+1);
  355. {$IfDef SYSTEMDEBUG}
  356. Writeln('arg ',i,' #',largs[i],'#');
  357. {$EndIf SYSTEMDEBUG}
  358. end;
  359. argc := proxy_argc;
  360. end;
  361. end;
  362. getmem(argv,argc shl 2);
  363. for i := 0 to argc-1 do
  364. argv[i] := largs[i];
  365. tempargv:=argv;
  366. {$ASMMODE DIRECT}
  367. asm
  368. movl tempargv,%eax
  369. movl %eax,_args
  370. end;
  371. {$ASMMODE ATT}
  372. end;
  373. function strcopy(dest,source : pchar) : pchar;
  374. begin
  375. asm
  376. cld
  377. movl 12(%ebp),%edi
  378. movl $0xffffffff,%ecx
  379. xorb %al,%al
  380. repne
  381. scasb
  382. not %ecx
  383. movl 8(%ebp),%edi
  384. movl 12(%ebp),%esi
  385. movl %ecx,%eax
  386. shrl $2,%ecx
  387. rep
  388. movsl
  389. movl %eax,%ecx
  390. andl $3,%ecx
  391. rep
  392. movsb
  393. movl 8(%ebp),%eax
  394. leave
  395. ret $8
  396. end;
  397. end;
  398. procedure setup_environment;
  399. var env_selector : word;
  400. env_count : longint;
  401. dos_env,cp : pchar;
  402. stubaddr : p_stub_info;
  403. begin
  404. {$ASMMODE DIRECT}
  405. asm
  406. movl __stubinfo,%eax
  407. movl %eax,stubaddr
  408. end;
  409. {$ASMMODE ATT}
  410. stub_info:=stubaddr;
  411. getmem(dos_env,stub_info^.env_size);
  412. env_count:=0;
  413. sysseg_move(stub_info^.psp_selector,$2c, get_ds, longint(@env_selector), 2);
  414. sysseg_move(env_selector, 0, get_ds, longint(dos_env), stub_info^.env_size);
  415. cp:=dos_env;
  416. while cp ^ <> #0 do
  417. begin
  418. inc(env_count);
  419. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  420. inc(longint(cp)); { skip to next character }
  421. end;
  422. getmem(envp,(env_count+1) * sizeof(pchar));
  423. if (envp = nil) then exit;
  424. cp:=dos_env;
  425. env_count:=0;
  426. while cp^ <> #0 do
  427. begin
  428. getmem(envp[env_count],strlen(cp)+1);
  429. strcopy(envp[env_count], cp);
  430. {$IfDef SYSTEMDEBUG}
  431. Writeln('env ',env_count,' = "',envp[env_count],'"');
  432. {$EndIf SYSTEMDEBUG}
  433. inc(env_count);
  434. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  435. inc(longint(cp)); { skip to next character }
  436. end;
  437. envp[env_count]:=nil;
  438. longint(cp):=longint(cp)+3;
  439. getmem(dos_argv0,strlen(cp)+1);
  440. if (dos_argv0 = nil) then halt;
  441. strcopy(dos_argv0, cp);
  442. { update ___dos_argv0 also }
  443. {$ASMMODE DIRECT}
  444. asm
  445. movl U_SYSTEM_DOS_ARGV0,%eax
  446. movl %eax,___dos_argv0
  447. end;
  448. {$ASMMODE ATT}
  449. end;
  450. procedure syscopytodos(addr : longint; len : longint);
  451. begin
  452. if len > tb_size then HandleError(217);
  453. sysseg_move(get_ds,addr,dos_selector,tb,len);
  454. end;
  455. procedure syscopyfromdos(addr : longint; len : longint);
  456. begin
  457. if len > tb_size then HandleError(217);
  458. sysseg_move(dos_selector,tb,get_ds,addr,len);
  459. end;
  460. procedure sysrealintr(intnr : word;var regs : trealregs);
  461. begin
  462. regs.realsp:=0;
  463. regs.realss:=0;
  464. asm
  465. movw intnr,%bx
  466. xorl %ecx,%ecx
  467. movl regs,%edi
  468. movw $0x300,%ax
  469. int $0x31
  470. end;
  471. end;
  472. function paramcount : longint;
  473. begin
  474. paramcount := argc - 1;
  475. end;
  476. function paramstr(l : longint) : string;
  477. begin
  478. if (l>=0) and (l+1<=argc) then
  479. paramstr:=strpas(argv[l])
  480. else
  481. paramstr:='';
  482. end;
  483. procedure randomize;
  484. var
  485. hl : longint;
  486. regs : trealregs;
  487. begin
  488. regs.realeax:=$2c00;
  489. sysrealintr($21,regs);
  490. hl:=regs.realedx and $ffff;
  491. randseed:=hl*$10000+ (regs.realecx and $ffff);
  492. end;
  493. {*****************************************************************************
  494. Heap Management
  495. *****************************************************************************}
  496. {$ASMMODE DIRECT}
  497. function Sbrk(size : longint):longint;assembler;
  498. asm
  499. movl size,%eax
  500. pushl %eax
  501. call ___sbrk
  502. addl $4,%esp
  503. end;
  504. {$ASMMODE ATT}
  505. { include standard heap management }
  506. {$I heap.inc}
  507. {****************************************************************************
  508. Low level File Routines
  509. ****************************************************************************}
  510. procedure AllowSlash(p:pchar);
  511. var
  512. i : longint;
  513. begin
  514. { allow slash as backslash }
  515. for i:=0 to strlen(p) do
  516. if p[i]='/' then p[i]:='\';
  517. end;
  518. {$ifdef SYSTEMDEBUG}
  519. { Keep Track of open files }
  520. const
  521. max_files = 50;
  522. var
  523. opennames : array [0..max_files-1] of pchar;
  524. openfiles : array [0..max_files-1] of boolean;
  525. {$endif SYSTEMDEBUG}
  526. procedure do_close(handle : longint);
  527. var
  528. regs : trealregs;
  529. begin
  530. regs.realebx:=handle;
  531. {$ifdef SYSTEMDEBUG}
  532. if handle<max_files then
  533. openfiles[handle]:=false;
  534. {$endif SYSTEMDEBUG}
  535. regs.realeax:=$3e00;
  536. sysrealintr($21,regs);
  537. end;
  538. procedure do_erase(p : pchar);
  539. var
  540. regs : trealregs;
  541. begin
  542. AllowSlash(p);
  543. syscopytodos(longint(p),strlen(p)+1);
  544. regs.realedx:=tb_offset;
  545. regs.realds:=tb_segment;
  546. {$ifndef RTLLITE}
  547. if LFNSupport then
  548. regs.realeax:=$7141
  549. else
  550. {$endif RTLLITE}
  551. regs.realeax:=$4100;
  552. regs.realesi:=0;
  553. regs.realecx:=0;
  554. sysrealintr($21,regs);
  555. if (regs.realflags and carryflag) <> 0 then
  556. InOutRes:=lo(regs.realeax);
  557. end;
  558. procedure do_rename(p1,p2 : pchar);
  559. var
  560. regs : trealregs;
  561. begin
  562. AllowSlash(p1);
  563. AllowSlash(p2);
  564. if strlen(p1)+strlen(p2)+3>tb_size then
  565. HandleError(217);
  566. sysseg_move(get_ds,longint(p2),dos_selector,tb,strlen(p2)+1);
  567. sysseg_move(get_ds,longint(p1),dos_selector,tb+strlen(p2)+2,strlen(p1)+1);
  568. regs.realedi:=tb_offset;
  569. regs.realedx:=tb_offset + strlen(p2)+2;
  570. regs.realds:=tb_segment;
  571. regs.reales:=tb_segment;
  572. {$ifndef RTLLITE}
  573. if LFNSupport then
  574. regs.realeax:=$7156
  575. else
  576. {$endif RTLLITE}
  577. regs.realeax:=$5600;
  578. regs.realecx:=$ff; { attribute problem here ! }
  579. sysrealintr($21,regs);
  580. if (regs.realflags and carryflag) <> 0 then
  581. InOutRes:=lo(regs.realeax);
  582. end;
  583. function do_write(h,addr,len : longint) : longint;
  584. var
  585. regs : trealregs;
  586. size,
  587. writesize : longint;
  588. begin
  589. writesize:=0;
  590. while len > 0 do
  591. begin
  592. if len>tb_size then
  593. size:=tb_size
  594. else
  595. size:=len;
  596. syscopytodos(addr+writesize,size);
  597. regs.realecx:=size;
  598. regs.realedx:=tb_offset;
  599. regs.realds:=tb_segment;
  600. regs.realebx:=h;
  601. regs.realeax:=$4000;
  602. sysrealintr($21,regs);
  603. if (regs.realflags and carryflag) <> 0 then
  604. begin
  605. InOutRes:=lo(regs.realeax);
  606. exit(writesize);
  607. end;
  608. len:=len-size;
  609. writesize:=writesize+size;
  610. end;
  611. Do_Write:=WriteSize
  612. end;
  613. function do_read(h,addr,len : longint) : longint;
  614. var
  615. regs : trealregs;
  616. size,
  617. readsize : longint;
  618. begin
  619. readsize:=0;
  620. while len > 0 do
  621. begin
  622. if len>tb_size then
  623. size:=tb_size
  624. else
  625. size:=len;
  626. regs.realecx:=size;
  627. regs.realedx:=tb_offset;
  628. regs.realds:=tb_segment;
  629. regs.realebx:=h;
  630. regs.realeax:=$3f00;
  631. sysrealintr($21,regs);
  632. if (regs.realflags and carryflag) <> 0 then
  633. begin
  634. InOutRes:=lo(regs.realeax);
  635. do_read:=0;
  636. exit;
  637. end
  638. else
  639. if regs.realeax<size then
  640. begin
  641. syscopyfromdos(addr+readsize,regs.realeax);
  642. do_read:=readsize+regs.realeax;
  643. exit;
  644. end;
  645. syscopyfromdos(addr+readsize,regs.realeax);
  646. readsize:=readsize+regs.realeax;
  647. len:=len-regs.realeax;
  648. end;
  649. do_read:=readsize;
  650. end;
  651. function do_filepos(handle : longint) : longint;
  652. var
  653. regs : trealregs;
  654. begin
  655. regs.realebx:=handle;
  656. regs.realecx:=0;
  657. regs.realedx:=0;
  658. regs.realeax:=$4201;
  659. sysrealintr($21,regs);
  660. if (regs.realflags and carryflag) <> 0 then
  661. Begin
  662. InOutRes:=lo(regs.realeax);
  663. do_filepos:=0;
  664. end
  665. else
  666. do_filepos:=lo(regs.realedx) shl 16+lo(regs.realeax);
  667. end;
  668. procedure do_seek(handle,pos : longint);
  669. var
  670. regs : trealregs;
  671. begin
  672. regs.realebx:=handle;
  673. regs.realecx:=pos shr 16;
  674. regs.realedx:=pos and $ffff;
  675. regs.realeax:=$4200;
  676. sysrealintr($21,regs);
  677. if (regs.realflags and carryflag) <> 0 then
  678. InOutRes:=lo(regs.realeax);
  679. end;
  680. function do_seekend(handle:longint):longint;
  681. var
  682. regs : trealregs;
  683. begin
  684. regs.realebx:=handle;
  685. regs.realecx:=0;
  686. regs.realedx:=0;
  687. regs.realeax:=$4202;
  688. sysrealintr($21,regs);
  689. if (regs.realflags and carryflag) <> 0 then
  690. Begin
  691. InOutRes:=lo(regs.realeax);
  692. do_seekend:=0;
  693. end
  694. else
  695. do_seekend:=lo(regs.realedx) shl 16+lo(regs.realeax);
  696. end;
  697. function do_filesize(handle : longint) : longint;
  698. var
  699. aktfilepos : longint;
  700. begin
  701. aktfilepos:=do_filepos(handle);
  702. do_filesize:=do_seekend(handle);
  703. do_seek(handle,aktfilepos);
  704. end;
  705. { truncate at a given position }
  706. procedure do_truncate (handle,pos:longint);
  707. var
  708. regs : trealregs;
  709. begin
  710. do_seek(handle,pos);
  711. regs.realecx:=0;
  712. regs.realedx:=tb_offset;
  713. regs.realds:=tb_segment;
  714. regs.realebx:=handle;
  715. regs.realeax:=$4000;
  716. sysrealintr($21,regs);
  717. if (regs.realflags and carryflag) <> 0 then
  718. InOutRes:=lo(regs.realeax);
  719. end;
  720. procedure do_open(var f;p:pchar;flags:longint);
  721. {
  722. filerec and textrec have both handle and mode as the first items so
  723. they could use the same routine for opening/creating.
  724. when (flags and $10) the file will be append
  725. when (flags and $100) the file will be truncate/rewritten
  726. when (flags and $1000) there is no check for close (needed for textfiles)
  727. }
  728. var
  729. regs : trealregs;
  730. action : longint;
  731. begin
  732. AllowSlash(p);
  733. { close first if opened }
  734. if ((flags and $1000)=0) then
  735. begin
  736. case filerec(f).mode of
  737. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  738. fmclosed : ;
  739. else
  740. begin
  741. inoutres:=102; {not assigned}
  742. exit;
  743. end;
  744. end;
  745. end;
  746. { reset file handle }
  747. filerec(f).handle:=UnusedHandle;
  748. action:=$1;
  749. { convert filemode to filerec modes }
  750. case (flags and 3) of
  751. 0 : filerec(f).mode:=fminput;
  752. 1 : filerec(f).mode:=fmoutput;
  753. 2 : filerec(f).mode:=fminout;
  754. end;
  755. if (flags and $100)<>0 then
  756. begin
  757. filerec(f).mode:=fmoutput;
  758. action:=$12; {create file function}
  759. end;
  760. { empty name is special }
  761. if p[0]=#0 then
  762. begin
  763. case filerec(f).mode of
  764. fminput : filerec(f).handle:=StdInputHandle;
  765. fmappend,
  766. fmoutput : begin
  767. filerec(f).handle:=StdOutputHandle;
  768. filerec(f).mode:=fmoutput; {fool fmappend}
  769. end;
  770. end;
  771. exit;
  772. end;
  773. { real dos call }
  774. syscopytodos(longint(p),strlen(p)+1);
  775. {$ifndef RTLLITE}
  776. if LFNSupport then
  777. regs.realeax:=$716c
  778. else
  779. {$endif RTLLITE}
  780. regs.realeax:=$6c00;
  781. regs.realedx:=action;
  782. regs.realds:=tb_segment;
  783. regs.realesi:=tb_offset;
  784. regs.realebx:=$2000+(flags and $ff);
  785. regs.realecx:=$20;
  786. sysrealintr($21,regs);
  787. if (regs.realflags and carryflag) <> 0 then
  788. begin
  789. InOutRes:=lo(regs.realeax);
  790. exit;
  791. end
  792. else
  793. filerec(f).handle:=regs.realeax;
  794. {$ifdef SYSTEMDEBUG}
  795. if regs.realeax<max_files then
  796. begin
  797. openfiles[regs.realeax]:=true;
  798. getmem(opennames[regs.realeax],strlen(p)+1);
  799. opennames[regs.realeax]:=p;
  800. end;
  801. {$endif SYSTEMDEBUG}
  802. { append mode }
  803. if (flags and $10)<>0 then
  804. begin
  805. do_seekend(filerec(f).handle);
  806. filerec(f).mode:=fmoutput; {fool fmappend}
  807. end;
  808. end;
  809. function do_isdevice(handle:longint):boolean;
  810. var
  811. regs : trealregs;
  812. begin
  813. regs.realebx:=handle;
  814. regs.realeax:=$4400;
  815. sysrealintr($21,regs);
  816. do_isdevice:=(regs.realedx and $80)<>0;
  817. if (regs.realflags and carryflag) <> 0 then
  818. InOutRes:=lo(regs.realeax);
  819. end;
  820. {*****************************************************************************
  821. UnTyped File Handling
  822. *****************************************************************************}
  823. {$i file.inc}
  824. {*****************************************************************************
  825. Typed File Handling
  826. *****************************************************************************}
  827. {$i typefile.inc}
  828. {*****************************************************************************
  829. Text File Handling
  830. *****************************************************************************}
  831. {$DEFINE EOF_CTRLZ}
  832. {$i text.inc}
  833. {*****************************************************************************
  834. Directory Handling
  835. *****************************************************************************}
  836. procedure DosDir(func:byte;const s:string);
  837. var
  838. buffer : array[0..255] of char;
  839. regs : trealregs;
  840. begin
  841. move(s[1],buffer,length(s));
  842. buffer[length(s)]:=#0;
  843. AllowSlash(pchar(@buffer));
  844. syscopytodos(longint(@buffer),length(s)+1);
  845. regs.realedx:=tb_offset;
  846. regs.realds:=tb_segment;
  847. {$ifndef RTLLITE}
  848. if LFNSupport then
  849. regs.realeax:=$7100+func
  850. else
  851. {$endif RTLLITE}
  852. regs.realeax:=func shl 8;
  853. sysrealintr($21,regs);
  854. if (regs.realflags and carryflag) <> 0 then
  855. InOutRes:=lo(regs.realeax);
  856. end;
  857. procedure mkdir(const s : string);[IOCheck];
  858. begin
  859. If InOutRes <> 0 then
  860. exit;
  861. DosDir($39,s);
  862. end;
  863. procedure rmdir(const s : string);[IOCheck];
  864. begin
  865. If InOutRes <> 0 then
  866. exit;
  867. DosDir($3a,s);
  868. end;
  869. procedure chdir(const s : string);[IOCheck];
  870. begin
  871. If InOutRes <> 0 then
  872. exit;
  873. DosDir($3b,s);
  874. end;
  875. procedure getdir(drivenr : byte;var dir : string);
  876. var
  877. temp : array[0..255] of char;
  878. i : longint;
  879. regs : trealregs;
  880. begin
  881. regs.realedx:=drivenr;
  882. regs.realesi:=tb_offset;
  883. regs.realds:=tb_segment;
  884. {$ifndef RTLLITE}
  885. if LFNSupport then
  886. regs.realeax:=$7147
  887. else
  888. {$endif RTLLITE}
  889. regs.realeax:=$4700;
  890. sysrealintr($21,regs);
  891. if (regs.realflags and carryflag) <> 0 then
  892. Begin
  893. InOutRes:=lo(regs.realeax);
  894. exit;
  895. end
  896. else
  897. syscopyfromdos(longint(@temp),251);
  898. { conversation to Pascal string including slash conversion }
  899. i:=0;
  900. while (temp[i]<>#0) do
  901. begin
  902. if temp[i]='/' then
  903. temp[i]:='\';
  904. dir[i+4]:=temp[i];
  905. inc(i);
  906. end;
  907. dir[2]:=':';
  908. dir[3]:='\';
  909. dir[0]:=char(i+3);
  910. { upcase the string }
  911. dir:=upcase(dir);
  912. if drivenr<>0 then { Drive was supplied. We know it }
  913. dir[1]:=char(65+drivenr-1)
  914. else
  915. begin
  916. { We need to get the current drive from DOS function 19H }
  917. { because the drive was the default, which can be unknown }
  918. regs.realeax:=$1900;
  919. sysrealintr($21,regs);
  920. i:= (regs.realeax and $ff) + ord('A');
  921. dir[1]:=chr(i);
  922. end;
  923. end;
  924. {*****************************************************************************
  925. SystemUnit Initialization
  926. *****************************************************************************}
  927. {$ifndef RTLLITE}
  928. function CheckLFN:boolean;
  929. var
  930. regs : TRealRegs;
  931. Buffers,
  932. RootName : pchar;
  933. begin
  934. RootName:='C:\'+#0;
  935. Buffers:=' '+#0;
  936. syscopytodos(longint(RootName),strlen(RootName)+1);
  937. regs.realeax:=$71a0;
  938. regs.reales:=tb_segment;
  939. regs.realedi:=tb_offset;
  940. regs.realecx:=strlen(Buffers)+1;
  941. regs.realds:=tb_segment;
  942. regs.realedx:=tb_offset;
  943. sysrealintr($21,regs);
  944. syscopyfromdos(longint(Buffers),strlen(Buffers)+1);
  945. CheckLFN:=(regs.realecx=255);
  946. end;
  947. {$endif RTLLITE}
  948. Begin
  949. { to test stack depth }
  950. loweststack:=maxlongint;
  951. { Setup heap }
  952. InitHeap;
  953. { Setup stdin, stdout and stderr }
  954. OpenStdIO(Input,fmInput,StdInputHandle);
  955. OpenStdIO(Output,fmOutput,StdOutputHandle);
  956. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  957. { Setup environment and arguments }
  958. Setup_Environment;
  959. Setup_Arguments;
  960. { Use LFNSupport LFN }
  961. LFNSupport:=CheckLFN;
  962. { Reset IO Error }
  963. InOutRes:=0;
  964. End.
  965. {
  966. $Log$
  967. Revision 1.17 1998-08-27 10:30:51 pierre
  968. * go32v1 RTL did not compile (LFNsupport outside go32v2 defines !)
  969. I renamed tb_selector to tb_segment because
  970. it is a real mode segment as opposed to
  971. a protected mode selector
  972. Fixed it for go32v1 (remove the $E0000000 offset !)
  973. Revision 1.16 1998/08/26 10:04:03 peter
  974. * new lfn check from mailinglist
  975. * renamed win95 -> LFNSupport
  976. + tb_selector, tb_offset for easier access to transferbuffer
  977. Revision 1.15 1998/08/19 10:56:34 pierre
  978. + added some special code for C interface
  979. to avoid loading of crt1.o or dpmiexcp.o from the libc.a
  980. Revision 1.14 1998/08/04 14:34:38 pierre
  981. * small bug fix to get it compiled with bugfix version !!
  982. (again the asmmode problem !!!
  983. Peter it was really not the best idea you had !!)
  984. Revision 1.13 1998/07/30 13:26:22 michael
  985. + Added support for ErrorProc variable. All internal functions are required
  986. to call HandleError instead of runerror from now on.
  987. This is necessary for exception support.
  988. Revision 1.12 1998/07/13 21:19:08 florian
  989. * some problems with ansi string support fixed
  990. Revision 1.11 1998/07/07 12:33:08 carl
  991. * added 2k buffer for stack checking for correct io on error
  992. Revision 1.10 1998/07/02 12:29:20 carl
  993. * IOCheck for rmdir,chdir and mkdir as in TP
  994. NOTE: I'm pretty SURE this will not compile and link correctly with FPC
  995. 0.99.5
  996. Revision 1.9 1998/07/01 15:29:57 peter
  997. * better readln/writeln
  998. Revision 1.8 1998/06/26 08:19:10 pierre
  999. + all debug in ifdef SYSTEMDEBUG
  1000. + added local arrays :
  1001. opennames names of opened files
  1002. fileopen boolean array to know if still open
  1003. usefull with gdb if you get problems about too
  1004. many open files !!
  1005. Revision 1.7 1998/06/15 15:17:08 daniel
  1006. * RTLLITE conditional added to produce smaller RTL.
  1007. Revision 1.6 1998/05/31 14:18:29 peter
  1008. * force att or direct assembling
  1009. * cleanup of some files
  1010. Revision 1.5 1998/05/21 19:30:52 peter
  1011. * objects compiles for linux
  1012. + assign(pchar), assign(char), rename(pchar), rename(char)
  1013. * fixed read_text_as_array
  1014. + read_text_as_pchar which was not yet in the rtl
  1015. Revision 1.4 1998/05/04 17:58:41 peter
  1016. * fix for smartlinking with _ARGS
  1017. Revision 1.3 1998/05/04 16:21:54 florian
  1018. + LFNSupport flag to the interface moved
  1019. }