system.pp 29 KB

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