system.pp 34 KB

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