system.pp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  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. Watcom
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit system;
  13. INTERFACE
  14. {$ifndef NO_EXCEPTIONS_IN_SYSTEM}
  15. {$define EXCEPTIONS_IN_SYSTEM}
  16. {$endif NO_EXCEPTIONS_IN_SYSTEM}
  17. { include system-independent routine headers }
  18. {$include systemh.inc}
  19. { include heap support headers }
  20. {$include heaph.inc}
  21. {Platform specific information}
  22. const
  23. LineEnding = #13#10;
  24. { LFNSupport is a variable here, defined below!!! }
  25. DirectorySeparator = '\';
  26. DriveSeparator = ':';
  27. PathSeparator = ';';
  28. { FileNameCaseSensitive is defined separately below!!! }
  29. const
  30. { Default filehandles }
  31. UnusedHandle = -1;
  32. StdInputHandle = 0;
  33. StdOutputHandle = 1;
  34. StdErrorHandle = 2;
  35. FileNameCaseSensitive : boolean = false;
  36. sLineBreak = LineEnding;
  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. {$ELSE RTLLITE}
  57. Const
  58. LFNSupport = false;
  59. {$endif RTLLITE}
  60. {
  61. necessary for objects.pas, should be removed (at least from the interface
  62. to the implementation)
  63. }
  64. type
  65. trealregs=record
  66. realedi,realesi,realebp,realres,
  67. realebx,realedx,realecx,realeax : longint;
  68. realflags,
  69. reales,realds,realfs,realgs,
  70. realip,realcs,realsp,realss : word;
  71. end;
  72. function do_write(h,addr,len : longint) : longint;
  73. function do_read(h,addr,len : longint) : longint;
  74. procedure syscopyfromdos(addr : longint; len : longint);
  75. procedure syscopytodos(addr : longint; len : longint);
  76. procedure sysrealintr(intnr : word;var regs : trealregs);
  77. var tb:longint;
  78. tb_segment:word;
  79. const tb_offset=0;
  80. tb_size=8192;
  81. IMPLEMENTATION
  82. { include system independent routines }
  83. {$include system.inc}
  84. const
  85. carryflag = 1;
  86. type
  87. tseginfo=packed record
  88. offset : pointer;
  89. segment : word;
  90. end;
  91. var
  92. old_int00 : tseginfo;cvar;
  93. old_int75 : tseginfo;cvar;
  94. {$asmmode ATT}
  95. {*****************************************************************************
  96. Watcom Helpers
  97. *****************************************************************************}
  98. function far_strlen(selector : word;linear_address : longint) : longint;assembler;
  99. asm
  100. movl linear_address,%edx
  101. movl %edx,%ecx
  102. movw selector,%gs
  103. .Larg19:
  104. movb %gs:(%edx),%al
  105. testb %al,%al
  106. je .Larg20
  107. incl %edx
  108. jmp .Larg19
  109. .Larg20:
  110. movl %edx,%eax
  111. subl %ecx,%eax
  112. end;
  113. function get_ds : word;assembler;
  114. asm
  115. movw %ds,%ax
  116. end;
  117. function get_cs : word;assembler;
  118. asm
  119. movw %cs,%ax
  120. end;
  121. function dos_selector : word; assembler;
  122. asm
  123. movw %ds,%ax { no separate selector needed }
  124. end;
  125. procedure alloc_tb; assembler;
  126. { allocate 8kB real mode transfer buffer }
  127. asm
  128. pushl %ebx
  129. movw $0x100,%ax
  130. movw $512,%bx
  131. int $0x31
  132. movw %ax,tb_segment
  133. shll $16,%eax
  134. shrl $12,%eax
  135. movl %eax,tb
  136. popl %ebx
  137. end;
  138. procedure sysseg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  139. begin
  140. if count=0 then
  141. exit;
  142. if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  143. asm
  144. pushl %esi
  145. pushl %edi
  146. pushw %es
  147. pushw %ds
  148. cld
  149. movl count,%ecx
  150. movl source,%esi
  151. movl dest,%edi
  152. movw dseg,%ax
  153. movw %ax,%es
  154. movw sseg,%ax
  155. movw %ax,%ds
  156. movl %ecx,%eax
  157. shrl $2,%ecx
  158. rep
  159. movsl
  160. movl %eax,%ecx
  161. andl $3,%ecx
  162. rep
  163. movsb
  164. popw %ds
  165. popw %es
  166. popl %edi
  167. popl %esi
  168. end
  169. else if (source<dest) then
  170. { copy backward for overlapping }
  171. asm
  172. pushl %esi
  173. pushl %edi
  174. pushw %es
  175. pushw %ds
  176. std
  177. movl count,%ecx
  178. movl source,%esi
  179. movl dest,%edi
  180. movw dseg,%ax
  181. movw %ax,%es
  182. movw sseg,%ax
  183. movw %ax,%ds
  184. addl %ecx,%esi
  185. addl %ecx,%edi
  186. movl %ecx,%eax
  187. andl $3,%ecx
  188. orl %ecx,%ecx
  189. jz .LSEG_MOVE1
  190. { calculate esi and edi}
  191. decl %esi
  192. decl %edi
  193. rep
  194. movsb
  195. incl %esi
  196. incl %edi
  197. .LSEG_MOVE1:
  198. subl $4,%esi
  199. subl $4,%edi
  200. movl %eax,%ecx
  201. shrl $2,%ecx
  202. rep
  203. movsl
  204. cld
  205. popw %ds
  206. popw %es
  207. popl %edi
  208. popl %esi
  209. end;
  210. end;
  211. var
  212. _args : ppchar;//###########external name '_args';
  213. procedure setup_arguments;
  214. begin
  215. // ####################################
  216. end;
  217. function strcopy(dest,source : pchar) : pchar;assembler;
  218. asm
  219. pushl %esi
  220. pushl %edi
  221. cld
  222. movl 12(%ebp),%edi
  223. movl $0xffffffff,%ecx
  224. xorb %al,%al
  225. repne
  226. scasb
  227. not %ecx
  228. movl 8(%ebp),%edi
  229. movl 12(%ebp),%esi
  230. movl %ecx,%eax
  231. shrl $2,%ecx
  232. rep
  233. movsl
  234. movl %eax,%ecx
  235. andl $3,%ecx
  236. rep
  237. movsb
  238. movl 8(%ebp),%eax
  239. popl %edi
  240. popl %esi
  241. end;
  242. procedure setup_environment;
  243. begin
  244. //#########################3
  245. end;
  246. procedure syscopytodos(addr : longint; len : longint);
  247. begin
  248. if len > tb_size then
  249. HandleError(217);
  250. sysseg_move(get_ds,addr,dos_selector,tb,len);
  251. end;
  252. procedure syscopyfromdos(addr : longint; len : longint);
  253. begin
  254. if len > tb_size then
  255. HandleError(217);
  256. sysseg_move(dos_selector,tb,get_ds,addr,len);
  257. end;
  258. procedure sysrealintr(intnr : word;var regs : trealregs);
  259. begin
  260. regs.realsp:=0;
  261. regs.realss:=0;
  262. asm
  263. pushl %edi
  264. pushl %ebx
  265. pushw %fs
  266. movw intnr,%bx
  267. xorl %ecx,%ecx
  268. movl regs,%edi
  269. movw $0x300,%ax
  270. int $0x31
  271. popw %fs
  272. popl %ebx
  273. popl %edi
  274. end;
  275. end;
  276. procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
  277. begin
  278. asm
  279. pushl %ebx
  280. movl intaddr,%eax
  281. movl (%eax),%edx
  282. movw 4(%eax),%cx
  283. movl $0x205,%eax
  284. movb vector,%bl
  285. int $0x31
  286. popl %ebx
  287. end;
  288. end;
  289. procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
  290. begin
  291. asm
  292. pushl %ebx
  293. movb vector,%bl
  294. movl $0x204,%eax
  295. int $0x31
  296. movl intaddr,%eax
  297. movl %edx,(%eax)
  298. movw %cx,4(%eax)
  299. popl %ebx
  300. end;
  301. end;
  302. procedure getinoutres(def : word);
  303. var
  304. regs : trealregs;
  305. begin
  306. regs.realeax:=$5900;
  307. regs.realebx:=$0;
  308. sysrealintr($21,regs);
  309. InOutRes:=lo(regs.realeax);
  310. case InOutRes of
  311. 19 : InOutRes:=150;
  312. 21 : InOutRes:=152;
  313. 32 : InOutRes:=5;
  314. end;
  315. if InOutRes=0 then
  316. InOutRes:=Def;
  317. end;
  318. { Keep Track of open files }
  319. const
  320. max_files = 50;
  321. var
  322. openfiles : array [0..max_files-1] of boolean;
  323. {$ifdef SYSTEMDEBUG}
  324. opennames : array [0..max_files-1] of pchar;
  325. const
  326. free_closed_names : boolean = true;
  327. {$endif SYSTEMDEBUG}
  328. {*****************************************************************************
  329. System Dependent Exit code
  330. *****************************************************************************}
  331. procedure ___exit(exitcode:longint);cdecl;external name '___exit';
  332. procedure do_close(handle : longint);forward;
  333. Procedure system_exit;
  334. var
  335. h : byte;
  336. begin
  337. for h:=0 to max_files-1 do
  338. if openfiles[h] then
  339. begin
  340. {$ifdef SYSTEMDEBUG}
  341. writeln(stderr,'file ',opennames[h],' not closed at exit');
  342. {$endif SYSTEMDEBUG}
  343. if h>=5 then
  344. do_close(h);
  345. end;
  346. { halt is not allways called !! }
  347. { not on normal exit !! PM }
  348. set_pm_interrupt($00,old_int00);
  349. {$ifndef EXCEPTIONS_IN_SYSTEM}
  350. set_pm_interrupt($75,old_int75);
  351. {$endif EXCEPTIONS_IN_SYSTEM}
  352. ___exit(exitcode);
  353. end;
  354. procedure new_int00;
  355. begin
  356. HandleError(200);
  357. end;
  358. {$ifndef EXCEPTIONS_IN_SYSTEM}
  359. procedure new_int75;
  360. begin
  361. asm
  362. xorl %eax,%eax
  363. outb %al,$0x0f0
  364. movb $0x20,%al
  365. outb %al,$0x0a0
  366. outb %al,$0x020
  367. end;
  368. HandleError(200);
  369. end;
  370. {$endif EXCEPTIONS_IN_SYSTEM}
  371. var
  372. __stkbottom : longint;//###########external name '__stkbottom';
  373. {*****************************************************************************
  374. ParamStr/Randomize
  375. *****************************************************************************}
  376. function paramcount : longint;
  377. begin
  378. paramcount := argc - 1;
  379. end;
  380. function paramstr(l : longint) : string;
  381. begin
  382. if (l>=0) and (l+1<=argc) then
  383. paramstr:=strpas(argv[l])
  384. else
  385. paramstr:='';
  386. end;
  387. procedure randomize;
  388. var
  389. hl : longint;
  390. regs : trealregs;
  391. begin
  392. regs.realeax:=$2c00;
  393. sysrealintr($21,regs);
  394. hl:=lo(regs.realedx);
  395. randseed:=hl*$10000+ lo(regs.realecx);
  396. end;
  397. {*****************************************************************************
  398. Heap Management
  399. *****************************************************************************}
  400. var int_heapsize:longint; external name 'HEAPSIZE';
  401. int_heap:longint; external name 'HEAP';
  402. function getheapstart:pointer;
  403. begin
  404. getheapstart:=@int_heap;
  405. end;
  406. function getheapsize:longint;
  407. begin
  408. getheapsize:=int_heapsize;
  409. end;
  410. function ___sbrk(size:longint):pointer;cdecl; external name '___sbrk';
  411. function Sbrk(size : longint):pointer;assembler;
  412. asm
  413. {$ifdef SYSTEMDEBUG}
  414. cmpb $1,accept_sbrk
  415. je .Lsbrk
  416. movl $0,%eax
  417. jmp .Lsbrk_fail
  418. .Lsbrk:
  419. {$endif}
  420. movl size,%eax
  421. pushl %eax
  422. call ___sbrk
  423. addl $4,%esp
  424. {$ifdef SYSTEMDEBUG}
  425. .Lsbrk_fail:
  426. {$endif}
  427. end;
  428. { include standard heap management }
  429. {$include heap.inc}
  430. {****************************************************************************
  431. Low level File Routines
  432. ****************************************************************************}
  433. procedure AllowSlash(p:pchar);
  434. var
  435. i : longint;
  436. begin
  437. { allow slash as backslash }
  438. for i:=0 to strlen(p) do
  439. if p[i]='/' then p[i]:='\';
  440. end;
  441. procedure do_close(handle : longint);
  442. var
  443. regs : trealregs;
  444. begin
  445. if Handle<=4 then
  446. exit;
  447. regs.realebx:=handle;
  448. if handle<max_files then
  449. begin
  450. openfiles[handle]:=false;
  451. {$ifdef SYSTEMDEBUG}
  452. if assigned(opennames[handle]) and free_closed_names then
  453. begin
  454. sysfreememsize(opennames[handle],strlen(opennames[handle])+1);
  455. opennames[handle]:=nil;
  456. end;
  457. {$endif SYSTEMDEBUG}
  458. end;
  459. regs.realeax:=$3e00;
  460. sysrealintr($21,regs);
  461. if (regs.realflags and carryflag) <> 0 then
  462. GetInOutRes(lo(regs.realeax));
  463. end;
  464. procedure do_erase(p : pchar);
  465. var
  466. regs : trealregs;
  467. begin
  468. AllowSlash(p);
  469. syscopytodos(longint(p),strlen(p)+1);
  470. regs.realedx:=tb_offset;
  471. regs.realds:=tb_segment;
  472. if LFNSupport then
  473. regs.realeax:=$7141
  474. else
  475. regs.realeax:=$4100;
  476. regs.realesi:=0;
  477. regs.realecx:=0;
  478. sysrealintr($21,regs);
  479. if (regs.realflags and carryflag) <> 0 then
  480. GetInOutRes(lo(regs.realeax));
  481. end;
  482. procedure do_rename(p1,p2 : pchar);
  483. var
  484. regs : trealregs;
  485. begin
  486. AllowSlash(p1);
  487. AllowSlash(p2);
  488. if strlen(p1)+strlen(p2)+3>tb_size then
  489. HandleError(217);
  490. sysseg_move(get_ds,longint(p2),dos_selector,tb,strlen(p2)+1);
  491. sysseg_move(get_ds,longint(p1),dos_selector,tb+strlen(p2)+2,strlen(p1)+1);
  492. regs.realedi:=tb_offset;
  493. regs.realedx:=tb_offset + strlen(p2)+2;
  494. regs.realds:=tb_segment;
  495. regs.reales:=tb_segment;
  496. if LFNSupport then
  497. regs.realeax:=$7156
  498. else
  499. regs.realeax:=$5600;
  500. regs.realecx:=$ff; { attribute problem here ! }
  501. sysrealintr($21,regs);
  502. if (regs.realflags and carryflag) <> 0 then
  503. GetInOutRes(lo(regs.realeax));
  504. end;
  505. function do_write(h,addr,len : longint) : longint;
  506. var
  507. regs : trealregs;
  508. size,
  509. writesize : longint;
  510. begin
  511. writesize:=0;
  512. while len > 0 do
  513. begin
  514. if len>tb_size then
  515. size:=tb_size
  516. else
  517. size:=len;
  518. syscopytodos(addr+writesize,size);
  519. regs.realecx:=size;
  520. regs.realedx:=tb_offset;
  521. regs.realds:=tb_segment;
  522. regs.realebx:=h;
  523. regs.realeax:=$4000;
  524. sysrealintr($21,regs);
  525. if (regs.realflags and carryflag) <> 0 then
  526. begin
  527. GetInOutRes(lo(regs.realeax));
  528. exit(writesize);
  529. end;
  530. inc(writesize,lo(regs.realeax));
  531. dec(len,lo(regs.realeax));
  532. { stop when not the specified size is written }
  533. if lo(regs.realeax)<size then
  534. break;
  535. end;
  536. Do_Write:=WriteSize;
  537. end;
  538. function do_read(h,addr,len : longint) : longint;
  539. var
  540. regs : trealregs;
  541. size,
  542. readsize : longint;
  543. begin
  544. readsize:=0;
  545. while len > 0 do
  546. begin
  547. if len>tb_size then
  548. size:=tb_size
  549. else
  550. size:=len;
  551. regs.realecx:=size;
  552. regs.realedx:=tb_offset;
  553. regs.realds:=tb_segment;
  554. regs.realebx:=h;
  555. regs.realeax:=$3f00;
  556. sysrealintr($21,regs);
  557. if (regs.realflags and carryflag) <> 0 then
  558. begin
  559. GetInOutRes(lo(regs.realeax));
  560. do_read:=0;
  561. exit;
  562. end;
  563. syscopyfromdos(addr+readsize,lo(regs.realeax));
  564. inc(readsize,lo(regs.realeax));
  565. dec(len,lo(regs.realeax));
  566. { stop when not the specified size is read }
  567. if lo(regs.realeax)<size then
  568. break;
  569. end;
  570. do_read:=readsize;
  571. end;
  572. function do_filepos(handle : longint) : longint;
  573. var
  574. regs : trealregs;
  575. begin
  576. regs.realebx:=handle;
  577. regs.realecx:=0;
  578. regs.realedx:=0;
  579. regs.realeax:=$4201;
  580. sysrealintr($21,regs);
  581. if (regs.realflags and carryflag) <> 0 then
  582. Begin
  583. GetInOutRes(lo(regs.realeax));
  584. do_filepos:=0;
  585. end
  586. else
  587. do_filepos:=lo(regs.realedx) shl 16+lo(regs.realeax);
  588. end;
  589. procedure do_seek(handle,pos : longint);
  590. var
  591. regs : trealregs;
  592. begin
  593. regs.realebx:=handle;
  594. regs.realecx:=pos shr 16;
  595. regs.realedx:=pos and $ffff;
  596. regs.realeax:=$4200;
  597. sysrealintr($21,regs);
  598. if (regs.realflags and carryflag) <> 0 then
  599. GetInOutRes(lo(regs.realeax));
  600. end;
  601. function do_seekend(handle:longint):longint;
  602. var
  603. regs : trealregs;
  604. begin
  605. regs.realebx:=handle;
  606. regs.realecx:=0;
  607. regs.realedx:=0;
  608. regs.realeax:=$4202;
  609. sysrealintr($21,regs);
  610. if (regs.realflags and carryflag) <> 0 then
  611. Begin
  612. GetInOutRes(lo(regs.realeax));
  613. do_seekend:=0;
  614. end
  615. else
  616. do_seekend:=lo(regs.realedx) shl 16+lo(regs.realeax);
  617. end;
  618. function do_filesize(handle : longint) : longint;
  619. var
  620. aktfilepos : longint;
  621. begin
  622. aktfilepos:=do_filepos(handle);
  623. do_filesize:=do_seekend(handle);
  624. do_seek(handle,aktfilepos);
  625. end;
  626. { truncate at a given position }
  627. procedure do_truncate (handle,pos:longint);
  628. var
  629. regs : trealregs;
  630. begin
  631. do_seek(handle,pos);
  632. regs.realecx:=0;
  633. regs.realedx:=tb_offset;
  634. regs.realds:=tb_segment;
  635. regs.realebx:=handle;
  636. regs.realeax:=$4000;
  637. sysrealintr($21,regs);
  638. if (regs.realflags and carryflag) <> 0 then
  639. GetInOutRes(lo(regs.realeax));
  640. end;
  641. const
  642. FileHandleCount : longint = 20;
  643. function Increase_file_handle_count : boolean;
  644. var
  645. regs : trealregs;
  646. begin
  647. Inc(FileHandleCount,10);
  648. regs.realebx:=FileHandleCount;
  649. regs.realeax:=$6700;
  650. sysrealintr($21,regs);
  651. if (regs.realflags and carryflag) <> 0 then
  652. begin
  653. Increase_file_handle_count:=false;
  654. Dec (FileHandleCount, 10);
  655. end
  656. else
  657. Increase_file_handle_count:=true;
  658. end;
  659. procedure do_open(var f;p:pchar;flags:longint);
  660. {
  661. filerec and textrec have both handle and mode as the first items so
  662. they could use the same routine for opening/creating.
  663. when (flags and $100) the file will be append
  664. when (flags and $1000) the file will be truncate/rewritten
  665. when (flags and $10000) there is no check for close (needed for textfiles)
  666. }
  667. var
  668. regs : trealregs;
  669. action : longint;
  670. begin
  671. AllowSlash(p);
  672. { close first if opened }
  673. if ((flags and $10000)=0) then
  674. begin
  675. case filerec(f).mode of
  676. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  677. fmclosed : ;
  678. else
  679. begin
  680. inoutres:=102; {not assigned}
  681. exit;
  682. end;
  683. end;
  684. end;
  685. { reset file handle }
  686. filerec(f).handle:=UnusedHandle;
  687. action:=$1;
  688. { convert filemode to filerec modes }
  689. case (flags and 3) of
  690. 0 : filerec(f).mode:=fminput;
  691. 1 : filerec(f).mode:=fmoutput;
  692. 2 : filerec(f).mode:=fminout;
  693. end;
  694. if (flags and $1000)<>0 then
  695. action:=$12; {create file function}
  696. { empty name is special }
  697. if p[0]=#0 then
  698. begin
  699. case FileRec(f).mode of
  700. fminput :
  701. FileRec(f).Handle:=StdInputHandle;
  702. fminout, { this is set by rewrite }
  703. fmoutput :
  704. FileRec(f).Handle:=StdOutputHandle;
  705. fmappend :
  706. begin
  707. FileRec(f).Handle:=StdOutputHandle;
  708. FileRec(f).mode:=fmoutput; {fool fmappend}
  709. end;
  710. end;
  711. exit;
  712. end;
  713. { real dos call }
  714. syscopytodos(longint(p),strlen(p)+1);
  715. if LFNSupport then
  716. regs.realeax:=$716c
  717. else
  718. regs.realeax:=$6c00;
  719. regs.realedx:=action;
  720. regs.realds:=tb_segment;
  721. regs.realesi:=tb_offset;
  722. regs.realebx:=$2000+(flags and $ff);
  723. regs.realecx:=$20;
  724. sysrealintr($21,regs);
  725. if (regs.realflags and carryflag) <> 0 then
  726. if lo(regs.realeax)=4 then
  727. if Increase_file_handle_count then
  728. begin
  729. { Try again }
  730. if LFNSupport then
  731. regs.realeax:=$716c
  732. else
  733. regs.realeax:=$6c00;
  734. regs.realedx:=action;
  735. regs.realds:=tb_segment;
  736. regs.realesi:=tb_offset;
  737. regs.realebx:=$2000+(flags and $ff);
  738. regs.realecx:=$20;
  739. sysrealintr($21,regs);
  740. end;
  741. if (regs.realflags and carryflag) <> 0 then
  742. begin
  743. GetInOutRes(lo(regs.realeax));
  744. exit;
  745. end
  746. else
  747. begin
  748. filerec(f).handle:=lo(regs.realeax);
  749. { for systems that have more then 20 by default ! }
  750. if lo(regs.realeax)>FileHandleCount then
  751. FileHandleCount:=lo(regs.realeax);
  752. end;
  753. if lo(regs.realeax)<max_files then
  754. begin
  755. {$ifdef SYSTEMDEBUG}
  756. if openfiles[lo(regs.realeax)] and
  757. assigned(opennames[lo(regs.realeax)]) then
  758. begin
  759. Writeln(stderr,'file ',opennames[lo(regs.realeax)],'(',lo(regs.realeax),') not closed but handle reused!');
  760. sysfreememsize(opennames[lo(regs.realeax)],strlen(opennames[lo(regs.realeax)])+1);
  761. end;
  762. {$endif SYSTEMDEBUG}
  763. openfiles[lo(regs.realeax)]:=true;
  764. {$ifdef SYSTEMDEBUG}
  765. opennames[lo(regs.realeax)] := sysgetmem(strlen(p)+1);
  766. move(p^,opennames[lo(regs.realeax)]^,strlen(p)+1);
  767. {$endif SYSTEMDEBUG}
  768. end;
  769. { append mode }
  770. if ((flags and $100) <> 0) and
  771. (FileRec (F).Handle <> UnusedHandle) then
  772. begin
  773. do_seekend(filerec(f).handle);
  774. filerec(f).mode:=fmoutput; {fool fmappend}
  775. end;
  776. end;
  777. function do_isdevice(handle:longint):boolean;
  778. var
  779. regs : trealregs;
  780. begin
  781. regs.realebx:=handle;
  782. regs.realeax:=$4400;
  783. sysrealintr($21,regs);
  784. do_isdevice:=(regs.realedx and $80)<>0;
  785. if (regs.realflags and carryflag) <> 0 then
  786. GetInOutRes(lo(regs.realeax));
  787. end;
  788. {*****************************************************************************
  789. UnTyped File Handling
  790. *****************************************************************************}
  791. {$i file.inc}
  792. {*****************************************************************************
  793. Typed File Handling
  794. *****************************************************************************}
  795. {$i typefile.inc}
  796. {*****************************************************************************
  797. Text File Handling
  798. *****************************************************************************}
  799. {$DEFINE EOF_CTRLZ}
  800. {$i text.inc}
  801. {*****************************************************************************
  802. Generic Handling
  803. *****************************************************************************}
  804. {$ifdef TEST_GENERIC}
  805. {$i generic.inc}
  806. {$endif TEST_GENERIC}
  807. {*****************************************************************************
  808. Directory Handling
  809. *****************************************************************************}
  810. procedure DosDir(func:byte;const s:string);
  811. var
  812. buffer : array[0..255] of char;
  813. regs : trealregs;
  814. begin
  815. move(s[1],buffer,length(s));
  816. buffer[length(s)]:=#0;
  817. AllowSlash(pchar(@buffer));
  818. { True DOS does not like backslashes at end
  819. Win95 DOS accepts this !!
  820. but "\" and "c:\" should still be kept and accepted hopefully PM }
  821. if (length(s)>0) and (buffer[length(s)-1]='\') and
  822. Not ((length(s)=1) or ((length(s)=3) and (s[2]=':'))) then
  823. buffer[length(s)-1]:=#0;
  824. syscopytodos(longint(@buffer),length(s)+1);
  825. regs.realedx:=tb_offset;
  826. regs.realds:=tb_segment;
  827. if LFNSupport then
  828. regs.realeax:=$7100+func
  829. else
  830. regs.realeax:=func shl 8;
  831. sysrealintr($21,regs);
  832. if (regs.realflags and carryflag) <> 0 then
  833. GetInOutRes(lo(regs.realeax));
  834. end;
  835. procedure mkdir(const s : string);[IOCheck];
  836. begin
  837. If (s='') or (InOutRes <> 0) then
  838. exit;
  839. DosDir($39,s);
  840. end;
  841. procedure rmdir(const s : string);[IOCheck];
  842. begin
  843. if (s = '.' ) then
  844. InOutRes := 16;
  845. If (s='') or (InOutRes <> 0) then
  846. exit;
  847. DosDir($3a,s);
  848. end;
  849. procedure chdir(const s : string);[IOCheck];
  850. var
  851. regs : trealregs;
  852. begin
  853. If (s='') or (InOutRes <> 0) then
  854. exit;
  855. { First handle Drive changes }
  856. if (length(s)>=2) and (s[2]=':') then
  857. begin
  858. regs.realedx:=(ord(s[1]) and (not 32))-ord('A');
  859. regs.realeax:=$0e00;
  860. sysrealintr($21,regs);
  861. regs.realeax:=$1900;
  862. sysrealintr($21,regs);
  863. if byte(regs.realeax)<>byte(regs.realedx) then
  864. begin
  865. Inoutres:=15;
  866. exit;
  867. end;
  868. { DosDir($3b,'c:') give Path not found error on
  869. pure DOS PM }
  870. if length(s)=2 then
  871. exit;
  872. end;
  873. { do the normal dos chdir }
  874. DosDir($3b,s);
  875. end;
  876. procedure getdir(drivenr : byte;var dir : shortstring);
  877. var
  878. temp : array[0..255] of char;
  879. i : longint;
  880. regs : trealregs;
  881. begin
  882. regs.realedx:=drivenr;
  883. regs.realesi:=tb_offset;
  884. regs.realds:=tb_segment;
  885. if LFNSupport then
  886. regs.realeax:=$7147
  887. else
  888. regs.realeax:=$4700;
  889. sysrealintr($21,regs);
  890. if (regs.realflags and carryflag) <> 0 then
  891. Begin
  892. GetInOutRes(lo(regs.realeax));
  893. Dir := char (DriveNr + 64) + ':\';
  894. exit;
  895. end
  896. else
  897. syscopyfromdos(longint(@temp),251);
  898. { conversion to Pascal string including slash conversion }
  899. i:=0;
  900. while (temp[i]<>#0) do
  901. begin
  902. if temp[i]='/' then
  903. temp[i]:='\';
  904. dir[i+4]:=temp[i];
  905. inc(i);
  906. end;
  907. dir[2]:=':';
  908. dir[3]:='\';
  909. dir[0]:=char(i+3);
  910. { upcase the string }
  911. if not FileNameCaseSensitive then
  912. dir:=upcase(dir);
  913. if drivenr<>0 then { Drive was supplied. We know it }
  914. dir[1]:=char(65+drivenr-1)
  915. else
  916. begin
  917. { We need to get the current drive from DOS function 19H }
  918. { because the drive was the default, which can be unknown }
  919. regs.realeax:=$1900;
  920. sysrealintr($21,regs);
  921. i:= (regs.realeax and $ff) + ord('A');
  922. dir[1]:=chr(i);
  923. end;
  924. end;
  925. {*****************************************************************************
  926. SystemUnit Initialization
  927. *****************************************************************************}
  928. function CheckLFN:boolean;
  929. var
  930. regs : TRealRegs;
  931. RootName : pchar;
  932. begin
  933. { Check LFN API on drive c:\ }
  934. RootName:='C:\';
  935. syscopytodos(longint(RootName),strlen(RootName)+1);
  936. { Call 'Get Volume Information' ($71A0) }
  937. regs.realeax:=$71a0;
  938. regs.reales:=tb_segment;
  939. regs.realedi:=tb_offset;
  940. regs.realecx:=32;
  941. regs.realds:=tb_segment;
  942. regs.realedx:=tb_offset;
  943. regs.realflags:=carryflag;
  944. //!! sysrealintr($21,regs); //!!wik
  945. { If carryflag=0 and LFN API bit in ebx is set then use Long file names }
  946. CheckLFN:=(regs.realflags and carryflag=0) and (regs.realebx and $4000=$4000);
  947. end;
  948. {$ifdef EXCEPTIONS_IN_SYSTEM}
  949. {$define IN_SYSTEM}
  950. {$i dpmiexcp.pp}
  951. {$endif EXCEPTIONS_IN_SYSTEM}
  952. procedure SysInitStdIO;
  953. begin
  954. OpenStdIO(Input,fmInput,StdInputHandle);
  955. OpenStdIO(Output,fmOutput,StdOutputHandle);
  956. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  957. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  958. end;
  959. var
  960. temp_int : tseginfo;
  961. Begin
  962. alloc_tb;
  963. StackLength := InitialStkLen;
  964. StackBottom := __stkbottom;
  965. { To be set if this is a GUI or console application }
  966. IsConsole := TRUE;
  967. { To be set if this is a library and not a program }
  968. IsLibrary := FALSE;
  969. { save old int 0 and 75 }
  970. get_pm_interrupt($00,old_int00);
  971. get_pm_interrupt($75,old_int75);
  972. temp_int.segment:=get_cs;
  973. temp_int.offset:=@new_int00;
  974. set_pm_interrupt($00,temp_int);
  975. {$ifndef EXCEPTIONS_IN_SYSTEM}
  976. temp_int.offset:=@new_int75;
  977. set_pm_interrupt($75,temp_int);
  978. {$endif EXCEPTIONS_IN_SYSTEM}
  979. { Setup heap }
  980. InitHeap;
  981. SysInitExceptions;
  982. { Setup stdin, stdout and stderr }
  983. SysInitStdIO;
  984. { Setup environment and arguments }
  985. // Setup_Environment;
  986. // Setup_Arguments;
  987. { Use LFNSupport LFN }
  988. LFNSupport:=CheckLFN;
  989. if LFNSupport then
  990. FileNameCaseSensitive:=true;
  991. { Reset IO Error }
  992. InOutRes:=0;
  993. {$ifdef EXCEPTIONS_IN_SYSTEM}
  994. InitDPMIExcp;
  995. InstallDefaultHandlers;
  996. {$endif EXCEPTIONS_IN_SYSTEM}
  997. {$ifdef HASVARIANT}
  998. initvariantmanager;
  999. {$endif HASVARIANT}
  1000. End.
  1001. END.
  1002. {
  1003. $Log$
  1004. Revision 1.5 2003-10-03 21:59:28 peter
  1005. * stdcall fixes
  1006. Revision 1.4 2003/09/29 18:52:36 hajny
  1007. * append fix applied to Amiga, Atari, EMX, GO32v2, OS/2 and Watcom
  1008. Revision 1.3 2003/09/27 11:52:36 peter
  1009. * sbrk returns pointer
  1010. Revision 1.2 2003/09/07 22:29:26 hajny
  1011. * syswat renamed to system, CVS log added
  1012. }