system.pp 34 KB

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