system.pp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 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. unit system;
  12. interface
  13. { two debug conditionnals can be used
  14. - SYSTEMDEBUG
  15. -for STACK checks
  16. -for non closed files at exit (or at any time with GDB)
  17. - SYSTEM_DEBUG_STARTUP
  18. specifically for
  19. - proxy command line (DJGPP feature)
  20. - list of args
  21. - list of env variables (PM) }
  22. {$ifndef NO_EXCEPTIONS_IN_SYSTEM}
  23. {$define EXCEPTIONS_IN_SYSTEM}
  24. {$endif NO_EXCEPTIONS_IN_SYSTEM}
  25. { include system-independent routine headers }
  26. {$I systemh.inc}
  27. { include heap support headers }
  28. {$I heaph.inc}
  29. {Platform specific information}
  30. type
  31. THandle = Longint;
  32. const
  33. LineEnding = #13#10;
  34. { LFNSupport is a variable here, defined below!!! }
  35. DirectorySeparator = '\';
  36. DriveSeparator = ':';
  37. PathSeparator = ';';
  38. { FileNameCaseSensitive is defined separately below!!! }
  39. const
  40. { Default filehandles }
  41. UnusedHandle = -1;
  42. StdInputHandle = 0;
  43. StdOutputHandle = 1;
  44. StdErrorHandle = 2;
  45. FileNameCaseSensitive : boolean = false;
  46. sLineBreak = LineEnding;
  47. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  48. { Default memory segments (Tp7 compatibility) }
  49. seg0040 = $0040;
  50. segA000 = $A000;
  51. segB000 = $B000;
  52. segB800 = $B800;
  53. var
  54. { Mem[] support }
  55. mem : array[0..$7fffffff] of byte absolute $0:$0;
  56. memw : array[0..$7fffffff div sizeof(word)] of word absolute $0:$0;
  57. meml : array[0..$7fffffff div sizeof(longint)] of longint absolute $0:$0;
  58. { C-compatible arguments and environment }
  59. argc : longint;
  60. argv : ppchar;
  61. envp : ppchar;
  62. dos_argv0 : pchar;
  63. {$ifndef RTLLITE}
  64. { System info }
  65. LFNSupport : boolean;
  66. {$ELSE RTLLITE}
  67. const
  68. LFNSupport = false;
  69. {$endif RTLLITE}
  70. type
  71. { Dos Extender info }
  72. p_stub_info = ^t_stub_info;
  73. t_stub_info = packed record
  74. magic : array[0..15] of char;
  75. size : longint;
  76. minstack : longint;
  77. memory_handle : longint;
  78. initial_size : longint;
  79. minkeep : word;
  80. ds_selector : word;
  81. ds_segment : word;
  82. psp_selector : word;
  83. cs_selector : word;
  84. env_size : word;
  85. basename : array[0..7] of char;
  86. argv0 : array [0..15] of char;
  87. dpmi_server : array [0..15] of char;
  88. end;
  89. p_go32_info_block = ^t_go32_info_block;
  90. t_go32_info_block = packed record
  91. size_of_this_structure_in_bytes : longint; {offset 0}
  92. linear_address_of_primary_screen : longint; {offset 4}
  93. linear_address_of_secondary_screen : longint; {offset 8}
  94. linear_address_of_transfer_buffer : longint; {offset 12}
  95. size_of_transfer_buffer : longint; {offset 16}
  96. pid : longint; {offset 20}
  97. master_interrupt_controller_base : byte; {offset 24}
  98. slave_interrupt_controller_base : byte; {offset 25}
  99. selector_for_linear_memory : word; {offset 26}
  100. linear_address_of_stub_info_structure : longint; {offset 28}
  101. linear_address_of_original_psp : longint; {offset 32}
  102. run_mode : word; {offset 36}
  103. run_mode_info : word; {offset 38}
  104. end;
  105. var
  106. stub_info : p_stub_info;
  107. go32_info_block : t_go32_info_block;
  108. {$ifdef SYSTEMDEBUG}
  109. const
  110. accept_sbrk : boolean = true;
  111. {$endif}
  112. {
  113. necessary for objects.pas, should be removed (at least from the interface
  114. to the implementation)
  115. }
  116. type
  117. trealregs=record
  118. realedi,realesi,realebp,realres,
  119. realebx,realedx,realecx,realeax : longint;
  120. realflags,
  121. reales,realds,realfs,realgs,
  122. realip,realcs,realsp,realss : word;
  123. end;
  124. function do_write(h:longint;addr:pointer;len : longint) : longint;
  125. function do_read(h:longint;addr:pointer;len : longint) : longint;
  126. procedure syscopyfromdos(addr : longint; len : longint);
  127. procedure syscopytodos(addr : longint; len : longint);
  128. procedure sysrealintr(intnr : word;var regs : trealregs);
  129. function tb : longint;
  130. implementation
  131. { include system independent routines }
  132. {$I system.inc}
  133. const
  134. carryflag = 1;
  135. type
  136. tseginfo=packed record
  137. offset : pointer;
  138. segment : word;
  139. end;
  140. var
  141. old_int00 : tseginfo;cvar;
  142. old_int75 : tseginfo;cvar;
  143. {$asmmode ATT}
  144. {*****************************************************************************
  145. Go32 Helpers
  146. *****************************************************************************}
  147. function far_strlen(selector : word;linear_address : longint) : longint;assembler;
  148. asm
  149. movl linear_address,%edx
  150. movl %edx,%ecx
  151. movw selector,%gs
  152. .Larg19:
  153. movb %gs:(%edx),%al
  154. testb %al,%al
  155. je .Larg20
  156. incl %edx
  157. jmp .Larg19
  158. .Larg20:
  159. movl %edx,%eax
  160. subl %ecx,%eax
  161. end;
  162. function tb : longint;
  163. begin
  164. tb:=go32_info_block.linear_address_of_transfer_buffer;
  165. end;
  166. function tb_segment : longint;
  167. begin
  168. tb_segment:=go32_info_block.linear_address_of_transfer_buffer shr 4;
  169. end;
  170. function tb_offset : longint;
  171. begin
  172. tb_offset:=go32_info_block.linear_address_of_transfer_buffer and $f;
  173. end;
  174. function tb_size : longint;
  175. begin
  176. tb_size:=go32_info_block.size_of_transfer_buffer;
  177. end;
  178. function dos_selector : word;
  179. begin
  180. dos_selector:=go32_info_block.selector_for_linear_memory;
  181. end;
  182. function get_ds : word;assembler;
  183. asm
  184. movw %ds,%ax
  185. end;
  186. function get_cs : word;assembler;
  187. asm
  188. movw %cs,%ax
  189. end;
  190. procedure sysseg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  191. begin
  192. if count=0 then
  193. exit;
  194. if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  195. asm
  196. pushl %esi
  197. pushl %edi
  198. pushw %es
  199. pushw %ds
  200. cld
  201. movl count,%ecx
  202. movl source,%esi
  203. movl dest,%edi
  204. movw dseg,%ax
  205. movw %ax,%es
  206. movw sseg,%ax
  207. movw %ax,%ds
  208. movl %ecx,%eax
  209. shrl $2,%ecx
  210. rep
  211. movsl
  212. movl %eax,%ecx
  213. andl $3,%ecx
  214. rep
  215. movsb
  216. popw %ds
  217. popw %es
  218. popl %edi
  219. popl %esi
  220. end
  221. else if (source<dest) then
  222. { copy backward for overlapping }
  223. asm
  224. pushl %esi
  225. pushl %edi
  226. pushw %es
  227. pushw %ds
  228. std
  229. movl count,%ecx
  230. movl source,%esi
  231. movl dest,%edi
  232. movw dseg,%ax
  233. movw %ax,%es
  234. movw sseg,%ax
  235. movw %ax,%ds
  236. addl %ecx,%esi
  237. addl %ecx,%edi
  238. movl %ecx,%eax
  239. andl $3,%ecx
  240. orl %ecx,%ecx
  241. jz .LSEG_MOVE1
  242. { calculate esi and edi}
  243. decl %esi
  244. decl %edi
  245. rep
  246. movsb
  247. incl %esi
  248. incl %edi
  249. .LSEG_MOVE1:
  250. subl $4,%esi
  251. subl $4,%edi
  252. movl %eax,%ecx
  253. shrl $2,%ecx
  254. rep
  255. movsl
  256. cld
  257. popw %ds
  258. popw %es
  259. popl %edi
  260. popl %esi
  261. end;
  262. end;
  263. var
  264. _args : ppchar;external name '_args';
  265. procedure setup_arguments;
  266. type
  267. arrayword = array [0..255] of word;
  268. var
  269. psp : word;
  270. proxy_s : string[50];
  271. proxy_argc,proxy_seg,proxy_ofs,lin : longint;
  272. rm_argv : ^arrayword;
  273. argv0len : longint;
  274. useproxy : boolean;
  275. hp : ppchar;
  276. doscmd : string[129]; { Dos commandline copied from PSP, max is 128 chars +1 for terminating zero }
  277. arglen,
  278. count : longint;
  279. argstart,
  280. pc,arg : pchar;
  281. quote : char;
  282. argvlen : longint;
  283. function atohex(s : pchar) : longint;
  284. var
  285. rv : longint;
  286. v : byte;
  287. begin
  288. rv:=0;
  289. while (s^<>#0) do
  290. begin
  291. v:=byte(s^)-byte('0');
  292. if (v > 9) then
  293. dec(v,7);
  294. v:=v and 15; { in case it's lower case }
  295. rv:=(rv shl 4) or v;
  296. inc(longint(s));
  297. end;
  298. atohex:=rv;
  299. end;
  300. procedure allocarg(idx,len:longint);
  301. begin
  302. if idx>=argvlen then
  303. begin
  304. argvlen:=(idx+8) and (not 7);
  305. sysreallocmem(argv,argvlen*sizeof(pointer));
  306. end;
  307. { use realloc to reuse already existing memory }
  308. if len<>0 then
  309. sysreallocmem(argv[idx],len+1);
  310. end;
  311. begin
  312. count:=0;
  313. argc:=1;
  314. argv:=nil;
  315. argvlen:=0;
  316. { load commandline from psp }
  317. psp:=stub_info^.psp_selector;
  318. sysseg_move(psp, 128, get_ds, longint(@doscmd), 128);
  319. doscmd[length(doscmd)+1]:=#0;
  320. {$IfDef SYSTEM_DEBUG_STARTUP}
  321. Writeln(stderr,'Dos command line is #',doscmd,'# size = ',length(doscmd));
  322. {$EndIf }
  323. { create argv[0] }
  324. argv0len:=strlen(dos_argv0);
  325. allocarg(count,argv0len);
  326. move(dos_argv0^,argv[count]^,argv0len);
  327. inc(count);
  328. { setup cmdline variable }
  329. cmdline:=Getmem(argv0len+length(doscmd)+2);
  330. move(dos_argv0^,cmdline^,argv0len);
  331. cmdline[argv0len]:=' ';
  332. inc(argv0len);
  333. move(doscmd[1],cmdline[argv0len],length(doscmd));
  334. cmdline[argv0len+length(doscmd)+1]:=#0;
  335. { parse dos commandline }
  336. pc:=@doscmd[1];
  337. while pc^<>#0 do
  338. begin
  339. { skip leading spaces }
  340. while pc^ in [#1..#32] do
  341. inc(pc);
  342. if pc^=#0 then
  343. break;
  344. { calc argument length }
  345. quote:=' ';
  346. argstart:=pc;
  347. arglen:=0;
  348. while (pc^<>#0) do
  349. begin
  350. case pc^ of
  351. #1..#32 :
  352. begin
  353. if quote<>' ' then
  354. inc(arglen)
  355. else
  356. break;
  357. end;
  358. '"' :
  359. begin
  360. if quote<>'''' then
  361. begin
  362. if pchar(pc+1)^<>'"' then
  363. begin
  364. if quote='"' then
  365. quote:=' '
  366. else
  367. quote:='"';
  368. end
  369. else
  370. inc(pc);
  371. end
  372. else
  373. inc(arglen);
  374. end;
  375. '''' :
  376. begin
  377. if quote<>'"' then
  378. begin
  379. if pchar(pc+1)^<>'''' then
  380. begin
  381. if quote='''' then
  382. quote:=' '
  383. else
  384. quote:='''';
  385. end
  386. else
  387. inc(pc);
  388. end
  389. else
  390. inc(arglen);
  391. end;
  392. else
  393. inc(arglen);
  394. end;
  395. inc(pc);
  396. end;
  397. { copy argument }
  398. allocarg(count,arglen);
  399. quote:=' ';
  400. pc:=argstart;
  401. arg:=argv[count];
  402. while (pc^<>#0) do
  403. begin
  404. case pc^ of
  405. #1..#32 :
  406. begin
  407. if quote<>' ' then
  408. begin
  409. arg^:=pc^;
  410. inc(arg);
  411. end
  412. else
  413. break;
  414. end;
  415. '"' :
  416. begin
  417. if quote<>'''' then
  418. begin
  419. if pchar(pc+1)^<>'"' then
  420. begin
  421. if quote='"' then
  422. quote:=' '
  423. else
  424. quote:='"';
  425. end
  426. else
  427. inc(pc);
  428. end
  429. else
  430. begin
  431. arg^:=pc^;
  432. inc(arg);
  433. end;
  434. end;
  435. '''' :
  436. begin
  437. if quote<>'"' then
  438. begin
  439. if pchar(pc+1)^<>'''' then
  440. begin
  441. if quote='''' then
  442. quote:=' '
  443. else
  444. quote:='''';
  445. end
  446. else
  447. inc(pc);
  448. end
  449. else
  450. begin
  451. arg^:=pc^;
  452. inc(arg);
  453. end;
  454. end;
  455. else
  456. begin
  457. arg^:=pc^;
  458. inc(arg);
  459. end;
  460. end;
  461. inc(pc);
  462. end;
  463. arg^:=#0;
  464. {$IfDef SYSTEM_DEBUG_STARTUP}
  465. Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
  466. {$EndIf SYSTEM_DEBUG_STARTUP}
  467. inc(count);
  468. end;
  469. argc:=count;
  470. { check for !proxy for long commandlines passed using environment }
  471. hp:=envp;
  472. useproxy:=false;
  473. while assigned(hp^) do
  474. begin
  475. if (hp^[0]=' ') then
  476. begin
  477. proxy_s:=strpas(hp^);
  478. if Copy(proxy_s,1,7)=' !proxy' then
  479. begin
  480. proxy_s[13]:=#0;
  481. proxy_s[18]:=#0;
  482. proxy_s[23]:=#0;
  483. argv[2]:=@proxy_s[9];
  484. argv[3]:=@proxy_s[14];
  485. argv[4]:=@proxy_s[19];
  486. useproxy:=true;
  487. break;
  488. end;
  489. end;
  490. inc(hp);
  491. end;
  492. { check for !proxy for long commandlines passed using commandline }
  493. if (not useproxy) and
  494. (argc > 1) and (far_strlen(get_ds,longint(argv[1])) = 6) then
  495. begin
  496. move(argv[1]^,proxy_s[1],6);
  497. proxy_s[0] := #6;
  498. if (proxy_s = '!proxy') then
  499. useproxy:=true;
  500. end;
  501. { use proxy when found }
  502. if useproxy then
  503. begin
  504. proxy_argc:=atohex(argv[2]);
  505. proxy_seg:=atohex(argv[3]);
  506. proxy_ofs:=atohex(argv[4]);
  507. {$IfDef SYSTEM_DEBUG_STARTUP}
  508. Writeln(stderr,'proxy command line found');
  509. writeln(stderr,'argc: ',proxy_argc,' seg: ',proxy_seg,' ofs: ',proxy_ofs);
  510. {$EndIf SYSTEM_DEBUG_STARTUP}
  511. rm_argv:=SysGetmem(proxy_argc*sizeof(word));
  512. sysseg_move(dos_selector,proxy_seg*16+proxy_ofs, get_ds,longint(rm_argv),proxy_argc*sizeof(word));
  513. for count:=0 to proxy_argc - 1 do
  514. begin
  515. lin:=proxy_seg*16+rm_argv^[count];
  516. arglen:=far_strlen(dos_selector,lin);
  517. allocarg(count,arglen);
  518. sysseg_move(dos_selector,lin,get_ds,longint(argv[count]),arglen+1);
  519. {$IfDef SYSTEM_DEBUG_STARTUP}
  520. Writeln(stderr,'arg ',count,' #',rm_argv^[count],'#',arglen,'#',argv[count],'#');
  521. {$EndIf SYSTEM_DEBUG_STARTUP}
  522. end;
  523. SysFreemem(rm_argv);
  524. argc:=proxy_argc;
  525. end;
  526. { create an nil entry }
  527. allocarg(argc,0);
  528. { free unused memory }
  529. sysreallocmem(argv,(argc+1)*sizeof(pointer));
  530. _args:=argv;
  531. end;
  532. function strcopy(dest,source : pchar) : pchar;assembler;
  533. var
  534. saveeax,saveesi,saveedi : longint;
  535. asm
  536. movl %edi,saveedi
  537. movl %esi,saveesi
  538. {$ifdef REGCALL}
  539. movl %eax,saveeax
  540. movl %edx,%edi
  541. {$else}
  542. movl source,%edi
  543. {$endif}
  544. testl %edi,%edi
  545. jz .LStrCopyDone
  546. leal 3(%edi),%ecx
  547. andl $-4,%ecx
  548. movl %edi,%esi
  549. subl %edi,%ecx
  550. {$ifdef REGCALL}
  551. movl %eax,%edi
  552. {$else}
  553. movl dest,%edi
  554. {$endif}
  555. jz .LStrCopyAligned
  556. .LStrCopyAlignLoop:
  557. movb (%esi),%al
  558. incl %edi
  559. incl %esi
  560. testb %al,%al
  561. movb %al,-1(%edi)
  562. jz .LStrCopyDone
  563. decl %ecx
  564. jnz .LStrCopyAlignLoop
  565. .balign 16
  566. .LStrCopyAligned:
  567. movl (%esi),%eax
  568. movl %eax,%edx
  569. leal 0x0fefefeff(%eax),%ecx
  570. notl %edx
  571. addl $4,%esi
  572. andl %edx,%ecx
  573. andl $0x080808080,%ecx
  574. jnz .LStrCopyEndFound
  575. movl %eax,(%edi)
  576. addl $4,%edi
  577. jmp .LStrCopyAligned
  578. .LStrCopyEndFound:
  579. testl $0x0ff,%eax
  580. jz .LStrCopyByte
  581. testl $0x0ff00,%eax
  582. jz .LStrCopyWord
  583. testl $0x0ff0000,%eax
  584. jz .LStrCopy3Bytes
  585. movl %eax,(%edi)
  586. jmp .LStrCopyDone
  587. .LStrCopy3Bytes:
  588. xorb %dl,%dl
  589. movw %ax,(%edi)
  590. movb %dl,2(%edi)
  591. jmp .LStrCopyDone
  592. .LStrCopyWord:
  593. movw %ax,(%edi)
  594. jmp .LStrCopyDone
  595. .LStrCopyByte:
  596. movb %al,(%edi)
  597. .LStrCopyDone:
  598. {$ifdef REGCALL}
  599. movl saveeax,%eax
  600. {$else}
  601. movl dest,%eax
  602. {$endif}
  603. movl saveedi,%edi
  604. movl saveesi,%esi
  605. end;
  606. var
  607. __stubinfo : p_stub_info;external name '__stubinfo';
  608. ___dos_argv0 : pchar;external name '___dos_argv0';
  609. procedure setup_environment;
  610. var env_selector : word;
  611. env_count : longint;
  612. dos_env,cp : pchar;
  613. begin
  614. stub_info:=__stubinfo;
  615. dos_env := sysgetmem(stub_info^.env_size);
  616. env_count:=0;
  617. sysseg_move(stub_info^.psp_selector,$2c, get_ds, longint(@env_selector), 2);
  618. sysseg_move(env_selector, 0, get_ds, longint(dos_env), stub_info^.env_size);
  619. cp:=dos_env;
  620. while cp ^ <> #0 do
  621. begin
  622. inc(env_count);
  623. while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
  624. inc(longint(cp)); { skip to next character }
  625. end;
  626. envp := sysgetmem((env_count+1) * sizeof(pchar));
  627. if (envp = nil) then exit;
  628. cp:=dos_env;
  629. env_count:=0;
  630. while cp^ <> #0 do
  631. begin
  632. envp[env_count] := sysgetmem(strlen(cp)+1);
  633. strcopy(envp[env_count], cp);
  634. {$IfDef SYSTEM_DEBUG_STARTUP}
  635. Writeln(stderr,'env ',env_count,' = "',envp[env_count],'"');
  636. {$EndIf SYSTEM_DEBUG_STARTUP}
  637. inc(env_count);
  638. while (cp^ <> #0) do
  639. inc(longint(cp)); { skip to NUL }
  640. inc(longint(cp)); { skip to next character }
  641. end;
  642. envp[env_count]:=nil;
  643. longint(cp):=longint(cp)+3;
  644. dos_argv0 := sysgetmem(strlen(cp)+1);
  645. if (dos_argv0 = nil) then halt;
  646. strcopy(dos_argv0, cp);
  647. { update ___dos_argv0 also }
  648. ___dos_argv0:=dos_argv0
  649. end;
  650. procedure syscopytodos(addr : longint; len : longint);
  651. begin
  652. if len > tb_size then
  653. HandleError(217);
  654. sysseg_move(get_ds,addr,dos_selector,tb,len);
  655. end;
  656. procedure syscopyfromdos(addr : longint; len : longint);
  657. begin
  658. if len > tb_size then
  659. HandleError(217);
  660. sysseg_move(dos_selector,tb,get_ds,addr,len);
  661. end;
  662. procedure sysrealintr(intnr : word;var regs : trealregs);
  663. begin
  664. regs.realsp:=0;
  665. regs.realss:=0;
  666. asm
  667. pushl %ebx
  668. pushl %edi
  669. movw intnr,%bx
  670. xorl %ecx,%ecx
  671. movl regs,%edi
  672. movw $0x300,%ax
  673. int $0x31
  674. popl %edi
  675. popl %ebx
  676. end;
  677. end;
  678. procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
  679. begin
  680. asm
  681. pushl %ebx
  682. movl intaddr,%eax
  683. movl (%eax),%edx
  684. movw 4(%eax),%cx
  685. movl $0x205,%eax
  686. movb vector,%bl
  687. int $0x31
  688. popl %ebx
  689. end;
  690. end;
  691. procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
  692. begin
  693. asm
  694. pushl %ebx
  695. movb vector,%bl
  696. movl $0x204,%eax
  697. int $0x31
  698. movl intaddr,%eax
  699. movl %edx,(%eax)
  700. movw %cx,4(%eax)
  701. popl %ebx
  702. end;
  703. end;
  704. procedure getinoutres(def : word);
  705. var
  706. regs : trealregs;
  707. begin
  708. regs.realeax:=$5900;
  709. regs.realebx:=$0;
  710. sysrealintr($21,regs);
  711. InOutRes:=lo(regs.realeax);
  712. case InOutRes of
  713. 19 : InOutRes:=150;
  714. 21 : InOutRes:=152;
  715. 32 : InOutRes:=5;
  716. end;
  717. if InOutRes=0 then
  718. InOutRes:=Def;
  719. end;
  720. { Keep Track of open files }
  721. const
  722. max_files = 50;
  723. var
  724. openfiles : array [0..max_files-1] of boolean;
  725. {$ifdef SYSTEMDEBUG}
  726. opennames : array [0..max_files-1] of pchar;
  727. const
  728. free_closed_names : boolean = true;
  729. {$endif SYSTEMDEBUG}
  730. {*****************************************************************************
  731. System Dependent Exit code
  732. *****************************************************************************}
  733. procedure ___exit(exitcode:longint);cdecl;external name '___exit';
  734. procedure do_close(handle : longint);forward;
  735. Procedure system_exit;
  736. var
  737. h : byte;
  738. begin
  739. for h:=0 to max_files-1 do
  740. if openfiles[h] then
  741. begin
  742. {$ifdef SYSTEMDEBUG}
  743. writeln(stderr,'file ',opennames[h],' not closed at exit');
  744. {$endif SYSTEMDEBUG}
  745. if h>=5 then
  746. do_close(h);
  747. end;
  748. { halt is not allways called !! }
  749. { not on normal exit !! PM }
  750. set_pm_interrupt($00,old_int00);
  751. {$ifndef EXCEPTIONS_IN_SYSTEM}
  752. set_pm_interrupt($75,old_int75);
  753. {$endif EXCEPTIONS_IN_SYSTEM}
  754. ___exit(exitcode);
  755. end;
  756. procedure new_int00;
  757. begin
  758. HandleError(200);
  759. end;
  760. {$ifndef EXCEPTIONS_IN_SYSTEM}
  761. procedure new_int75;
  762. begin
  763. asm
  764. xorl %eax,%eax
  765. outb %al,$0x0f0
  766. movb $0x20,%al
  767. outb %al,$0x0a0
  768. outb %al,$0x020
  769. end;
  770. HandleError(200);
  771. end;
  772. {$endif EXCEPTIONS_IN_SYSTEM}
  773. var
  774. __stkbottom : pointer;external name '__stkbottom';
  775. {*****************************************************************************
  776. ParamStr/Randomize
  777. *****************************************************************************}
  778. function paramcount : longint;
  779. begin
  780. paramcount := argc - 1;
  781. end;
  782. function paramstr(l : longint) : string;
  783. begin
  784. if (l>=0) and (l+1<=argc) then
  785. paramstr:=strpas(argv[l])
  786. else
  787. paramstr:='';
  788. end;
  789. procedure randomize;
  790. var
  791. hl : longint;
  792. regs : trealregs;
  793. begin
  794. regs.realeax:=$2c00;
  795. sysrealintr($21,regs);
  796. hl:=lo(regs.realedx);
  797. randseed:=hl*$10000+ lo(regs.realecx);
  798. end;
  799. {*****************************************************************************
  800. Heap Management
  801. *****************************************************************************}
  802. var
  803. int_heap : longint;external name 'HEAP';
  804. int_heapsize : longint;external name 'HEAPSIZE';
  805. function getheapstart:pointer;
  806. begin
  807. getheapstart:=@int_heap;
  808. end;
  809. function getheapsize:longint;
  810. begin
  811. getheapsize:=int_heapsize;
  812. end;
  813. function ___sbrk(size:longint):longint;cdecl;external name '___sbrk';
  814. function Sbrk(size : longint):pointer;assembler;
  815. asm
  816. {$ifdef SYSTEMDEBUG}
  817. cmpb $1,accept_sbrk
  818. je .Lsbrk
  819. movl $0,%eax
  820. jmp .Lsbrk_fail
  821. .Lsbrk:
  822. {$endif}
  823. movl size,%eax
  824. pushl %eax
  825. call ___sbrk
  826. addl $4,%esp
  827. {$ifdef SYSTEMDEBUG}
  828. .Lsbrk_fail:
  829. {$endif}
  830. end;
  831. { include standard heap management }
  832. {$I heap.inc}
  833. {****************************************************************************
  834. Low level File Routines
  835. ****************************************************************************}
  836. procedure AllowSlash(p:pchar);
  837. var
  838. i : longint;
  839. begin
  840. { allow slash as backslash }
  841. for i:=0 to strlen(p) do
  842. if p[i]='/' then p[i]:='\';
  843. end;
  844. procedure do_close(handle : longint);
  845. var
  846. regs : trealregs;
  847. begin
  848. if Handle<=4 then
  849. exit;
  850. regs.realebx:=handle;
  851. if handle<max_files then
  852. begin
  853. openfiles[handle]:=false;
  854. {$ifdef SYSTEMDEBUG}
  855. if assigned(opennames[handle]) and free_closed_names then
  856. begin
  857. sysfreememsize(opennames[handle],strlen(opennames[handle])+1);
  858. opennames[handle]:=nil;
  859. end;
  860. {$endif SYSTEMDEBUG}
  861. end;
  862. regs.realeax:=$3e00;
  863. sysrealintr($21,regs);
  864. if (regs.realflags and carryflag) <> 0 then
  865. GetInOutRes(lo(regs.realeax));
  866. end;
  867. procedure do_erase(p : pchar);
  868. var
  869. regs : trealregs;
  870. begin
  871. AllowSlash(p);
  872. syscopytodos(longint(p),strlen(p)+1);
  873. regs.realedx:=tb_offset;
  874. regs.realds:=tb_segment;
  875. if LFNSupport then
  876. regs.realeax:=$7141
  877. else
  878. regs.realeax:=$4100;
  879. regs.realesi:=0;
  880. regs.realecx:=0;
  881. sysrealintr($21,regs);
  882. if (regs.realflags and carryflag) <> 0 then
  883. GetInOutRes(lo(regs.realeax));
  884. end;
  885. procedure do_rename(p1,p2 : pchar);
  886. var
  887. regs : trealregs;
  888. begin
  889. AllowSlash(p1);
  890. AllowSlash(p2);
  891. if strlen(p1)+strlen(p2)+3>tb_size then
  892. HandleError(217);
  893. sysseg_move(get_ds,longint(p2),dos_selector,tb,strlen(p2)+1);
  894. sysseg_move(get_ds,longint(p1),dos_selector,tb+strlen(p2)+2,strlen(p1)+1);
  895. regs.realedi:=tb_offset;
  896. regs.realedx:=tb_offset + strlen(p2)+2;
  897. regs.realds:=tb_segment;
  898. regs.reales:=tb_segment;
  899. if LFNSupport then
  900. regs.realeax:=$7156
  901. else
  902. regs.realeax:=$5600;
  903. regs.realecx:=$ff; { attribute problem here ! }
  904. sysrealintr($21,regs);
  905. if (regs.realflags and carryflag) <> 0 then
  906. GetInOutRes(lo(regs.realeax));
  907. end;
  908. function do_write(h:longint;addr:pointer;len : longint) : longint;
  909. var
  910. regs : trealregs;
  911. size,
  912. writesize : longint;
  913. begin
  914. writesize:=0;
  915. while len > 0 do
  916. begin
  917. if len>tb_size then
  918. size:=tb_size
  919. else
  920. size:=len;
  921. syscopytodos(ptrint(addr)+writesize,size);
  922. regs.realecx:=size;
  923. regs.realedx:=tb_offset;
  924. regs.realds:=tb_segment;
  925. regs.realebx:=h;
  926. regs.realeax:=$4000;
  927. sysrealintr($21,regs);
  928. if (regs.realflags and carryflag) <> 0 then
  929. begin
  930. GetInOutRes(lo(regs.realeax));
  931. exit(writesize);
  932. end;
  933. inc(writesize,lo(regs.realeax));
  934. dec(len,lo(regs.realeax));
  935. { stop when not the specified size is written }
  936. if lo(regs.realeax)<size then
  937. break;
  938. end;
  939. Do_Write:=WriteSize;
  940. end;
  941. function do_read(h:longint;addr:pointer;len : longint) : longint;
  942. var
  943. regs : trealregs;
  944. size,
  945. readsize : longint;
  946. begin
  947. readsize:=0;
  948. while len > 0 do
  949. begin
  950. if len>tb_size then
  951. size:=tb_size
  952. else
  953. size:=len;
  954. regs.realecx:=size;
  955. regs.realedx:=tb_offset;
  956. regs.realds:=tb_segment;
  957. regs.realebx:=h;
  958. regs.realeax:=$3f00;
  959. sysrealintr($21,regs);
  960. if (regs.realflags and carryflag) <> 0 then
  961. begin
  962. GetInOutRes(lo(regs.realeax));
  963. do_read:=0;
  964. exit;
  965. end;
  966. syscopyfromdos(ptrint(addr)+readsize,lo(regs.realeax));
  967. inc(readsize,lo(regs.realeax));
  968. dec(len,lo(regs.realeax));
  969. { stop when not the specified size is read }
  970. if lo(regs.realeax)<size then
  971. break;
  972. end;
  973. do_read:=readsize;
  974. end;
  975. function do_filepos(handle : longint) : longint;
  976. var
  977. regs : trealregs;
  978. begin
  979. regs.realebx:=handle;
  980. regs.realecx:=0;
  981. regs.realedx:=0;
  982. regs.realeax:=$4201;
  983. sysrealintr($21,regs);
  984. if (regs.realflags and carryflag) <> 0 then
  985. Begin
  986. GetInOutRes(lo(regs.realeax));
  987. do_filepos:=0;
  988. end
  989. else
  990. do_filepos:=lo(regs.realedx) shl 16+lo(regs.realeax);
  991. end;
  992. procedure do_seek(handle,pos : longint);
  993. var
  994. regs : trealregs;
  995. begin
  996. regs.realebx:=handle;
  997. regs.realecx:=pos shr 16;
  998. regs.realedx:=pos and $ffff;
  999. regs.realeax:=$4200;
  1000. sysrealintr($21,regs);
  1001. if (regs.realflags and carryflag) <> 0 then
  1002. GetInOutRes(lo(regs.realeax));
  1003. end;
  1004. function do_seekend(handle:longint):longint;
  1005. var
  1006. regs : trealregs;
  1007. begin
  1008. regs.realebx:=handle;
  1009. regs.realecx:=0;
  1010. regs.realedx:=0;
  1011. regs.realeax:=$4202;
  1012. sysrealintr($21,regs);
  1013. if (regs.realflags and carryflag) <> 0 then
  1014. Begin
  1015. GetInOutRes(lo(regs.realeax));
  1016. do_seekend:=0;
  1017. end
  1018. else
  1019. do_seekend:=lo(regs.realedx) shl 16+lo(regs.realeax);
  1020. end;
  1021. function do_filesize(handle : longint) : longint;
  1022. var
  1023. aktfilepos : longint;
  1024. begin
  1025. aktfilepos:=do_filepos(handle);
  1026. do_filesize:=do_seekend(handle);
  1027. do_seek(handle,aktfilepos);
  1028. end;
  1029. { truncate at a given position }
  1030. procedure do_truncate (handle,pos:longint);
  1031. var
  1032. regs : trealregs;
  1033. begin
  1034. do_seek(handle,pos);
  1035. regs.realecx:=0;
  1036. regs.realedx:=tb_offset;
  1037. regs.realds:=tb_segment;
  1038. regs.realebx:=handle;
  1039. regs.realeax:=$4000;
  1040. sysrealintr($21,regs);
  1041. if (regs.realflags and carryflag) <> 0 then
  1042. GetInOutRes(lo(regs.realeax));
  1043. end;
  1044. const
  1045. FileHandleCount : longint = 20;
  1046. function Increase_file_handle_count : boolean;
  1047. var
  1048. regs : trealregs;
  1049. begin
  1050. Inc(FileHandleCount,10);
  1051. regs.realebx:=FileHandleCount;
  1052. regs.realeax:=$6700;
  1053. sysrealintr($21,regs);
  1054. if (regs.realflags and carryflag) <> 0 then
  1055. begin
  1056. Increase_file_handle_count:=false;
  1057. Dec (FileHandleCount, 10);
  1058. end
  1059. else
  1060. Increase_file_handle_count:=true;
  1061. end;
  1062. function dos_version : word;
  1063. var
  1064. regs : trealregs;
  1065. begin
  1066. regs.realeax := $3000;
  1067. sysrealintr($21,regs);
  1068. dos_version := regs.realeax
  1069. end;
  1070. procedure do_open(var f;p:pchar;flags:longint);
  1071. {
  1072. filerec and textrec have both handle and mode as the first items so
  1073. they could use the same routine for opening/creating.
  1074. when (flags and $100) the file will be append
  1075. when (flags and $1000) the file will be truncate/rewritten
  1076. when (flags and $10000) there is no check for close (needed for textfiles)
  1077. }
  1078. var
  1079. regs : trealregs;
  1080. action : longint;
  1081. Avoid6c00 : boolean;
  1082. begin
  1083. AllowSlash(p);
  1084. { check if Extended Open/Create API is safe to use }
  1085. Avoid6c00 := lo(dos_version) < 7;
  1086. { close first if opened }
  1087. if ((flags and $10000)=0) then
  1088. begin
  1089. case filerec(f).mode of
  1090. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  1091. fmclosed : ;
  1092. else
  1093. begin
  1094. inoutres:=102; {not assigned}
  1095. exit;
  1096. end;
  1097. end;
  1098. end;
  1099. { reset file handle }
  1100. filerec(f).handle:=UnusedHandle;
  1101. action:=$1;
  1102. { convert filemode to filerec modes }
  1103. case (flags and 3) of
  1104. 0 : filerec(f).mode:=fminput;
  1105. 1 : filerec(f).mode:=fmoutput;
  1106. 2 : filerec(f).mode:=fminout;
  1107. end;
  1108. if (flags and $1000)<>0 then
  1109. action:=$12; {create file function}
  1110. { empty name is special }
  1111. if p[0]=#0 then
  1112. begin
  1113. case FileRec(f).mode of
  1114. fminput :
  1115. FileRec(f).Handle:=StdInputHandle;
  1116. fminout, { this is set by rewrite }
  1117. fmoutput :
  1118. FileRec(f).Handle:=StdOutputHandle;
  1119. fmappend :
  1120. begin
  1121. FileRec(f).Handle:=StdOutputHandle;
  1122. FileRec(f).mode:=fmoutput; {fool fmappend}
  1123. end;
  1124. end;
  1125. exit;
  1126. end;
  1127. { real dos call }
  1128. syscopytodos(longint(p),strlen(p)+1);
  1129. {$ifndef RTLLITE}
  1130. if LFNSupport then
  1131. regs.realeax := $716c { Use LFN Open/Create API }
  1132. else
  1133. {$endif RTLLITE}
  1134. if Avoid6c00 then
  1135. regs.realeax := $3d00 + (flags and $ff) { For now, map to Open API }
  1136. else
  1137. regs.realeax := $6c00; { Use Extended Open/Create API }
  1138. if byte(regs.realeax shr 8) = $3d then
  1139. begin { Using the older Open or Create API's }
  1140. if (action and $00f0) <> 0 then
  1141. regs.realeax := $3c00; { Map to Create/Replace API }
  1142. regs.realds := tb_segment;
  1143. regs.realedx := tb_offset;
  1144. end
  1145. else
  1146. begin { Using LFN or Extended Open/Create API }
  1147. regs.realedx := action; { action if file does/doesn't exist }
  1148. regs.realds := tb_segment;
  1149. regs.realesi := tb_offset;
  1150. regs.realebx := $2000 + (flags and $ff); { file open mode }
  1151. end;
  1152. regs.realecx := $20; { file attributes }
  1153. sysrealintr($21,regs);
  1154. {$ifndef RTLLITE}
  1155. if (regs.realflags and carryflag) <> 0 then
  1156. if lo(regs.realeax)=4 then
  1157. if Increase_file_handle_count then
  1158. begin
  1159. { Try again }
  1160. if LFNSupport then
  1161. regs.realeax := $716c {Use LFN Open/Create API}
  1162. else
  1163. if Avoid6c00 then
  1164. regs.realeax := $3d00+(flags and $ff) {For now, map to Open API}
  1165. else
  1166. regs.realeax := $6c00; {Use Extended Open/Create API}
  1167. if byte(regs.realeax shr 8) = $3d then
  1168. begin { Using the older Open or Create API's }
  1169. if (action and $00f0) <> 0 then
  1170. regs.realeax := $3c00; {Map to Create/Replace API}
  1171. regs.realds := tb_segment;
  1172. regs.realedx := tb_offset;
  1173. end
  1174. else
  1175. begin { Using LFN or Extended Open/Create API }
  1176. regs.realedx := action; {action if file does/doesn't exist}
  1177. regs.realds := tb_segment;
  1178. regs.realesi := tb_offset;
  1179. regs.realebx := $2000+(flags and $ff); {file open mode}
  1180. end;
  1181. regs.realecx := $20; {file attributes}
  1182. sysrealintr($21,regs);
  1183. end;
  1184. {$endif RTLLITE}
  1185. if (regs.realflags and carryflag) <> 0 then
  1186. begin
  1187. GetInOutRes(lo(regs.realeax));
  1188. exit;
  1189. end
  1190. else
  1191. begin
  1192. filerec(f).handle:=lo(regs.realeax);
  1193. {$ifndef RTLLITE}
  1194. { for systems that have more then 20 by default ! }
  1195. if lo(regs.realeax)>FileHandleCount then
  1196. FileHandleCount:=lo(regs.realeax);
  1197. {$endif RTLLITE}
  1198. end;
  1199. if lo(regs.realeax)<max_files then
  1200. begin
  1201. {$ifdef SYSTEMDEBUG}
  1202. if openfiles[lo(regs.realeax)] and
  1203. assigned(opennames[lo(regs.realeax)]) then
  1204. begin
  1205. Writeln(stderr,'file ',opennames[lo(regs.realeax)],'(',lo(regs.realeax),') not closed but handle reused!');
  1206. sysfreememsize(opennames[lo(regs.realeax)],strlen(opennames[lo(regs.realeax)])+1);
  1207. end;
  1208. {$endif SYSTEMDEBUG}
  1209. openfiles[lo(regs.realeax)]:=true;
  1210. {$ifdef SYSTEMDEBUG}
  1211. opennames[lo(regs.realeax)] := sysgetmem(strlen(p)+1);
  1212. move(p^,opennames[lo(regs.realeax)]^,strlen(p)+1);
  1213. {$endif SYSTEMDEBUG}
  1214. end;
  1215. { append mode }
  1216. if (flags and $100)<>0 then
  1217. begin
  1218. do_seekend(filerec(f).handle);
  1219. filerec(f).mode:=fmoutput; {fool fmappend}
  1220. end;
  1221. end;
  1222. function do_isdevice(handle:longint):boolean;
  1223. var
  1224. regs : trealregs;
  1225. begin
  1226. regs.realebx:=handle;
  1227. regs.realeax:=$4400;
  1228. sysrealintr($21,regs);
  1229. do_isdevice:=(regs.realedx and $80)<>0;
  1230. if (regs.realflags and carryflag) <> 0 then
  1231. GetInOutRes(lo(regs.realeax));
  1232. end;
  1233. {*****************************************************************************
  1234. UnTyped File Handling
  1235. *****************************************************************************}
  1236. {$i file.inc}
  1237. {*****************************************************************************
  1238. Typed File Handling
  1239. *****************************************************************************}
  1240. {$i typefile.inc}
  1241. {*****************************************************************************
  1242. Text File Handling
  1243. *****************************************************************************}
  1244. {$DEFINE EOF_CTRLZ}
  1245. {$i text.inc}
  1246. {*****************************************************************************
  1247. Generic Handling
  1248. *****************************************************************************}
  1249. {$ifdef TEST_GENERIC}
  1250. {$i generic.inc}
  1251. {$endif TEST_GENERIC}
  1252. {*****************************************************************************
  1253. Directory Handling
  1254. *****************************************************************************}
  1255. procedure DosDir(func:byte;const s:string);
  1256. var
  1257. buffer : array[0..255] of char;
  1258. regs : trealregs;
  1259. begin
  1260. move(s[1],buffer,length(s));
  1261. buffer[length(s)]:=#0;
  1262. AllowSlash(pchar(@buffer));
  1263. { True DOS does not like backslashes at end
  1264. Win95 DOS accepts this !!
  1265. but "\" and "c:\" should still be kept and accepted hopefully PM }
  1266. if (length(s)>0) and (buffer[length(s)-1]='\') and
  1267. Not ((length(s)=1) or ((length(s)=3) and (s[2]=':'))) then
  1268. buffer[length(s)-1]:=#0;
  1269. syscopytodos(longint(@buffer),length(s)+1);
  1270. regs.realedx:=tb_offset;
  1271. regs.realds:=tb_segment;
  1272. if LFNSupport then
  1273. regs.realeax:=$7100+func
  1274. else
  1275. regs.realeax:=func shl 8;
  1276. sysrealintr($21,regs);
  1277. if (regs.realflags and carryflag) <> 0 then
  1278. GetInOutRes(lo(regs.realeax));
  1279. end;
  1280. procedure mkdir(const s : string);[IOCheck];
  1281. begin
  1282. If (s='') or (InOutRes <> 0) then
  1283. exit;
  1284. DosDir($39,s);
  1285. end;
  1286. procedure rmdir(const s : string);[IOCheck];
  1287. begin
  1288. if (s = '.' ) then
  1289. InOutRes := 16;
  1290. If (s='') or (InOutRes <> 0) then
  1291. exit;
  1292. DosDir($3a,s);
  1293. end;
  1294. procedure chdir(const s : string);[IOCheck];
  1295. var
  1296. regs : trealregs;
  1297. begin
  1298. If (s='') or (InOutRes <> 0) then
  1299. exit;
  1300. { First handle Drive changes }
  1301. if (length(s)>=2) and (s[2]=':') then
  1302. begin
  1303. regs.realedx:=(ord(s[1]) and (not 32))-ord('A');
  1304. regs.realeax:=$0e00;
  1305. sysrealintr($21,regs);
  1306. regs.realeax:=$1900;
  1307. sysrealintr($21,regs);
  1308. if byte(regs.realeax)<>byte(regs.realedx) then
  1309. begin
  1310. Inoutres:=15;
  1311. exit;
  1312. end;
  1313. { DosDir($3b,'c:') give Path not found error on
  1314. pure DOS PM }
  1315. if length(s)=2 then
  1316. exit;
  1317. end;
  1318. { do the normal dos chdir }
  1319. DosDir($3b,s);
  1320. end;
  1321. procedure GetDir (DriveNr: byte; var Dir: ShortString);
  1322. var
  1323. temp : array[0..255] of char;
  1324. i : longint;
  1325. regs : trealregs;
  1326. begin
  1327. regs.realedx:=drivenr;
  1328. regs.realesi:=tb_offset;
  1329. regs.realds:=tb_segment;
  1330. if LFNSupport then
  1331. regs.realeax:=$7147
  1332. else
  1333. regs.realeax:=$4700;
  1334. sysrealintr($21,regs);
  1335. if (regs.realflags and carryflag) <> 0 then
  1336. Begin
  1337. GetInOutRes (lo(regs.realeax));
  1338. Dir := char (DriveNr + 64) + ':\';
  1339. exit;
  1340. end
  1341. else
  1342. syscopyfromdos(longint(@temp),251);
  1343. { conversion to Pascal string including slash conversion }
  1344. i:=0;
  1345. while (temp[i]<>#0) do
  1346. begin
  1347. if temp[i]='/' then
  1348. temp[i]:='\';
  1349. dir[i+4]:=temp[i];
  1350. inc(i);
  1351. end;
  1352. dir[2]:=':';
  1353. dir[3]:='\';
  1354. dir[0]:=char(i+3);
  1355. { upcase the string }
  1356. if not FileNameCaseSensitive then
  1357. dir:=upcase(dir);
  1358. if drivenr<>0 then { Drive was supplied. We know it }
  1359. dir[1]:=char(65+drivenr-1)
  1360. else
  1361. begin
  1362. { We need to get the current drive from DOS function 19H }
  1363. { because the drive was the default, which can be unknown }
  1364. regs.realeax:=$1900;
  1365. sysrealintr($21,regs);
  1366. i:= (regs.realeax and $ff) + ord('A');
  1367. dir[1]:=chr(i);
  1368. end;
  1369. end;
  1370. {*****************************************************************************
  1371. SystemUnit Initialization
  1372. *****************************************************************************}
  1373. function CheckLFN:boolean;
  1374. var
  1375. regs : TRealRegs;
  1376. RootName : pchar;
  1377. begin
  1378. { Check LFN API on drive c:\ }
  1379. RootName:='C:\';
  1380. syscopytodos(longint(RootName),strlen(RootName)+1);
  1381. { Call 'Get Volume Information' ($71A0) }
  1382. regs.realeax:=$71a0;
  1383. regs.reales:=tb_segment;
  1384. regs.realedi:=tb_offset;
  1385. regs.realecx:=32;
  1386. regs.realds:=tb_segment;
  1387. regs.realedx:=tb_offset;
  1388. regs.realflags:=carryflag;
  1389. sysrealintr($21,regs);
  1390. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  1391. CheckLFN:=(regs.realflags and carryflag=0) and (regs.realebx and $4000=$4000);
  1392. end;
  1393. {$ifdef EXCEPTIONS_IN_SYSTEM}
  1394. {$define IN_SYSTEM}
  1395. {$i dpmiexcp.pp}
  1396. {$endif EXCEPTIONS_IN_SYSTEM}
  1397. procedure SysInitStdIO;
  1398. begin
  1399. OpenStdIO(Input,fmInput,StdInputHandle);
  1400. OpenStdIO(Output,fmOutput,StdOutputHandle);
  1401. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  1402. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  1403. end;
  1404. var
  1405. temp_int : tseginfo;
  1406. Begin
  1407. StackLength := InitialStkLen;
  1408. StackBottom := __stkbottom;
  1409. { To be set if this is a GUI or console application }
  1410. IsConsole := TRUE;
  1411. { To be set if this is a library and not a program }
  1412. IsLibrary := FALSE;
  1413. { save old int 0 and 75 }
  1414. get_pm_interrupt($00,old_int00);
  1415. get_pm_interrupt($75,old_int75);
  1416. temp_int.segment:=get_cs;
  1417. temp_int.offset:=@new_int00;
  1418. set_pm_interrupt($00,temp_int);
  1419. {$ifndef EXCEPTIONS_IN_SYSTEM}
  1420. temp_int.offset:=@new_int75;
  1421. set_pm_interrupt($75,temp_int);
  1422. {$endif EXCEPTIONS_IN_SYSTEM}
  1423. { Setup heap }
  1424. InitHeap;
  1425. SysInitExceptions;
  1426. { Setup stdin, stdout and stderr }
  1427. SysInitStdIO;
  1428. { Setup environment and arguments }
  1429. Setup_Environment;
  1430. Setup_Arguments;
  1431. { Use LFNSupport LFN }
  1432. LFNSupport:=CheckLFN;
  1433. if LFNSupport then
  1434. FileNameCaseSensitive:=true;
  1435. { Reset IO Error }
  1436. InOutRes:=0;
  1437. {$ifdef EXCEPTIONS_IN_SYSTEM}
  1438. InitDPMIExcp;
  1439. InstallDefaultHandlers;
  1440. {$endif EXCEPTIONS_IN_SYSTEM}
  1441. {$ifdef HASVARIANT}
  1442. initvariantmanager;
  1443. {$endif HASVARIANT}
  1444. End.
  1445. {
  1446. $Log$
  1447. Revision 1.34 2004-04-22 21:10:56 peter
  1448. * do_read/do_write addr argument changed to pointer
  1449. Revision 1.33 2004/01/25 13:05:08 jonas
  1450. * fixed compilation errors
  1451. Revision 1.32 2004/01/20 23:09:14 hajny
  1452. * ExecuteProcess fixes, ProcessID and ThreadID added
  1453. Revision 1.31 2004/01/10 10:49:24 jonas
  1454. * fixed compilation
  1455. Revision 1.30 2003/12/17 20:40:38 hajny
  1456. * 'conservative' version of the do_open patch by Joe da Silva
  1457. Revision 1.29 2003/12/04 21:42:07 peter
  1458. * register calling updates
  1459. Revision 1.28 2003/11/03 09:42:27 marco
  1460. * Peter's Cardinal<->Longint fixes patch
  1461. Revision 1.27 2003/10/16 15:43:13 peter
  1462. * THandle is platform dependent
  1463. Revision 1.26 2003/10/03 21:46:25 peter
  1464. * stdcall fixes
  1465. Revision 1.25 2003/09/29 18:39:59 hajny
  1466. * append fix applied to GO32v2, OS/2 and EMX
  1467. Revision 1.24 2003/09/27 11:52:35 peter
  1468. * sbrk returns pointer
  1469. Revision 1.23 2002/10/14 19:39:16 peter
  1470. * threads unit added for thread support
  1471. Revision 1.22 2002/10/13 09:28:44 florian
  1472. + call to initvariantmanager inserted
  1473. Revision 1.21 2002/09/07 21:32:08 carl
  1474. - removed unused defines
  1475. Revision 1.20 2002/09/07 16:01:19 peter
  1476. * old logs removed and tabs fixed
  1477. Revision 1.19 2002/07/01 16:29:05 peter
  1478. * sLineBreak changed to normal constant like Kylix
  1479. Revision 1.18 2002/05/05 10:23:54 peter
  1480. * fixed memw and meml array sizes
  1481. Revision 1.17 2002/04/21 15:52:58 carl
  1482. + initialize some global variables
  1483. Revision 1.16 2002/04/12 17:34:05 carl
  1484. + generic stack checking
  1485. Revision 1.15 2002/03/11 19:10:33 peter
  1486. * Regenerated with updated fpcmake
  1487. }