system.pp 37 KB

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