system.pp 31 KB

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