system.pp 27 KB

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