system.pp 26 KB

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