system.pp 35 KB

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