system.pas 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. {
  2. $Id$
  3. ****************************************************************************
  4. Free Pascal -- OS/2 runtime library
  5. Copyright (c) 1999-2000 by Florian Klaempfl
  6. Copyright (c) 1999-2000 by Daniel Mantione
  7. Free Pascal is distributed under the GNU Public License v2. So is this unit.
  8. The GNU Public License requires you to distribute the source code of this
  9. unit with any product that uses it. We grant you an exception to this, and
  10. that is, when you compile a program with the Free Pascal Compiler, you do not
  11. need to ship source code with that program, AS LONG AS YOU ARE USING
  12. UNMODIFIED CODE! If you modify this code, you MUST change the next line:
  13. <This an official, unmodified Free Pascal source code file.>
  14. Send us your modified files, we can work together if you want!
  15. Free Pascal is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. Library GNU General Public License for more details.
  19. You should have received a copy of the Library GNU General Public License
  20. along with Free Pascal; see the file COPYING.LIB. If not, write to
  21. the Free Software Foundation, 59 Temple Place - Suite 330,
  22. Boston, MA 02111-1307, USA.
  23. ****************************************************************************}
  24. unit {$ifdef VER1_0}sysos2{$else}System{$endif};
  25. {Changelog:
  26. People:
  27. DM - Daniel Mantione
  28. Date: Description of change: Changed by:
  29. - First released version 0.1. DM
  30. Coding style:
  31. My coding style is a bit unusual for Pascal. Nevertheless I friendly ask
  32. you to try to make your changes not look all to different. In general,
  33. set your IDE to use a tabsize of 4.}
  34. interface
  35. {Link the startup code.}
  36. {$l prt1.oo2}
  37. {$I SYSTEMH.INC}
  38. type
  39. { FK: The fields of this record are OS dependent and they shouldn't }
  40. { be used in a program; only the type TCriticalSection is important. }
  41. (* TH: To make things easier, I copied the record definition *)
  42. (* from the Win32 version and just added longint variants, *)
  43. (* because it seemed well suited for OS/2 too. *)
  44. TCriticalSection = packed record
  45. DebugInfo: pointer;
  46. LockCount: longint;
  47. RecursionCount: longint;
  48. case boolean of
  49. false:
  50. (OwningThread: DWord;
  51. LockSemaphore: DWord;
  52. Reserved: DWord);
  53. true:
  54. (OwningThread2: longint;
  55. LockSemaphore2: longint;
  56. Reserved2: longint);
  57. end;
  58. { include threading stuff }
  59. {$i threadh.inc}
  60. {$I heaph.inc}
  61. type Tos=(osDOS,osOS2,osDPMI);
  62. var os_mode:Tos;
  63. first_meg:pointer;
  64. type Psysthreadib=^Tsysthreadib;
  65. Pthreadinfoblock=^Tthreadinfoblock;
  66. PPThreadInfoBlock=^PThreadInfoBlock;
  67. Pprocessinfoblock=^Tprocessinfoblock;
  68. PPProcessInfoBlock=^PProcessInfoBlock;
  69. Tbytearray=array[0..$ffff] of byte;
  70. Pbytearray=^Tbytearray;
  71. Tsysthreadib=record
  72. tid,
  73. priority,
  74. version:longint;
  75. MCcount,
  76. MCforceflag:word;
  77. end;
  78. Tthreadinfoblock=record
  79. pexchain,
  80. stack,
  81. stacklimit:pointer;
  82. tib2:Psysthreadib;
  83. version,
  84. ordinal:longint;
  85. end;
  86. Tprocessinfoblock=record
  87. pid,
  88. parentpid,
  89. hmte:longint;
  90. cmd,
  91. env:Pbytearray;
  92. flstatus,
  93. ttype:longint;
  94. end;
  95. const UnusedHandle=$ffff;
  96. StdInputHandle=0;
  97. StdOutputHandle=1;
  98. StdErrorHandle=2;
  99. FileNameCaseSensitive : boolean = false;
  100. sLineBreak : string[2] = #13#10;
  101. var
  102. { C-compatible arguments and environment }
  103. argc : longint;external name '_argc';
  104. argv : ppchar;external name '_argv';
  105. envp : ppchar;external name '_environ';
  106. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  107. implementation
  108. {$I SYSTEM.INC}
  109. var
  110. heap_base: pointer; external name '__heap_base';
  111. heap_brk: pointer; external name '__heap_brk';
  112. procedure DosGetInfoBlocks (PATIB: PPThreadInfoBlock;
  113. PAPIB: PPProcessInfoBlock); cdecl;
  114. external 'DOSCALLS' index 312;
  115. function DosSetRelMaxFH (var ReqCount, CurMaxFH: longint): longint; cdecl;
  116. external 'DOSCALLS' index 382;
  117. function DosSetCurrentDir (Name:PChar): longint; cdecl;
  118. external 'DOSCALLS' index 255;
  119. function DosSetDefaultDisk (DiskNum:longint): longint; cdecl;
  120. external 'DOSCALLS' index 220;
  121. {This is the correct way to call external assembler procedures.}
  122. procedure syscall; external name '___SYSCALL';
  123. {***************************************************************************
  124. Runtime error checking related routines.
  125. ***************************************************************************}
  126. {$S-}
  127. procedure st1(stack_size:longint); assembler; [public,alias: 'FPC_STACKCHECK'];
  128. { called when trying to get local stack }
  129. { if the compiler directive $S is set }
  130. asm
  131. movl stack_size,%ebx
  132. movl %esp,%eax
  133. subl %ebx,%eax
  134. {$ifdef SYSTEMDEBUG}
  135. movl loweststack,%ebx
  136. cmpl %eax,%ebx
  137. jb .Lis_not_lowest
  138. movl %eax,loweststack
  139. .Lis_not_lowest:
  140. {$endif SYSTEMDEBUG}
  141. cmpb osOS2,os_mode
  142. jne .Lrunning_in_dos
  143. movl stackbottom,%ebx
  144. jmp .Lrunning_in_os2
  145. .Lrunning_in_dos:
  146. movl heap_brk,%ebx
  147. .Lrunning_in_os2:
  148. cmpl %eax,%ebx
  149. jae .Lshort_on_stack
  150. .Lshort_on_stack:
  151. pushl $202
  152. call HandleError
  153. end ['EAX','EBX'];
  154. {no stack check in system }
  155. {****************************************************************************
  156. Miscellaneous related routines.
  157. ****************************************************************************}
  158. {$asmmode intel}
  159. procedure system_exit; assembler;
  160. asm
  161. mov ah, 04ch
  162. mov al, byte ptr exitcode
  163. call syscall
  164. end ['EAX'];
  165. {$ASMMODE ATT}
  166. function paramcount:longint;assembler;
  167. asm
  168. movl argc,%eax
  169. decl %eax
  170. end ['EAX'];
  171. function paramstr(l:longint):string;
  172. function args:pointer;assembler;
  173. asm
  174. movl argv,%eax
  175. end ['EAX'];
  176. var p:^Pchar;
  177. begin
  178. if L = 0 then
  179. begin
  180. GetMem (P, 260);
  181. {$ASMMODE INTEL}
  182. asm
  183. mov edx, P
  184. mov ecx, 260
  185. mov eax, 7F33h
  186. call syscall
  187. end;
  188. ParamStr := StrPas (PChar (P));
  189. FreeMem (P, 260);
  190. end
  191. else
  192. if (l>0) and (l<=paramcount) then
  193. begin
  194. p:=args;
  195. paramstr:=strpas(p[l]);
  196. end
  197. else paramstr:='';
  198. end;
  199. {
  200. procedure randomize;
  201. var hl:longint;
  202. begin
  203. asm
  204. movb $0x2c,%ah
  205. call syscall
  206. movw %cx,-4(%ebp)
  207. movw %dx,-2(%ebp)
  208. end;
  209. randseed:=hl;
  210. end;
  211. }
  212. procedure randomize; assembler;
  213. asm
  214. mov ah, 2Ch
  215. call syscall
  216. mov word ptr [randseed], cx
  217. mov word ptr [randseed + 2], dx
  218. end;
  219. {$ASMMODE ATT}
  220. {****************************************************************************
  221. Heap management releated routines.
  222. ****************************************************************************}
  223. { this function allows to extend the heap by calling
  224. syscall $7f00 resizes the brk area}
  225. function sbrk(size:longint):longint; assembler;
  226. asm
  227. movl size,%edx
  228. movw $0x7f00,%ax
  229. call syscall
  230. end;
  231. function getheapstart:pointer;assembler;
  232. asm
  233. movl heap_base,%eax
  234. end ['EAX'];
  235. function getheapsize:longint;assembler;
  236. asm
  237. movl HeapSize,%eax
  238. end ['EAX'];
  239. {$i heap.inc}
  240. {****************************************************************************
  241. Low Level File Routines
  242. ****************************************************************************}
  243. procedure allowslash(p:Pchar);
  244. {Allow slash as backslash.}
  245. var i:longint;
  246. begin
  247. for i:=0 to strlen(p) do
  248. if p[i]='/' then p[i]:='\';
  249. end;
  250. procedure do_close(h:longint);
  251. begin
  252. { Only three standard handles under real OS/2 }
  253. if (h > 4) or
  254. (os_MODE = osOS2) and (h > 2) then
  255. begin
  256. asm
  257. movb $0x3e,%ah
  258. movl h,%ebx
  259. call syscall
  260. end;
  261. end;
  262. end;
  263. procedure do_erase(p:Pchar);
  264. begin
  265. allowslash(p);
  266. asm
  267. movl P,%edx
  268. movb $0x41,%ah
  269. call syscall
  270. jnc .LERASE1
  271. movw %ax,inoutres;
  272. .LERASE1:
  273. end;
  274. end;
  275. procedure do_rename(p1,p2:Pchar);
  276. begin
  277. allowslash(p1);
  278. allowslash(p2);
  279. asm
  280. movl P1, %edx
  281. movl P2, %edi
  282. movb $0x56,%ah
  283. call syscall
  284. jnc .LRENAME1
  285. movw %ax,inoutres;
  286. .LRENAME1:
  287. end;
  288. end;
  289. function do_read(h,addr,len:longint):longint; assembler;
  290. asm
  291. movl len,%ecx
  292. movl addr,%edx
  293. movl h,%ebx
  294. movb $0x3f,%ah
  295. call syscall
  296. jnc .LDOSREAD1
  297. movw %ax,inoutres;
  298. xorl %eax,%eax
  299. .LDOSREAD1:
  300. end;
  301. function do_write(h,addr,len:longint) : longint; assembler;
  302. asm
  303. movl len,%ecx
  304. movl addr,%edx
  305. movl h,%ebx
  306. movb $0x40,%ah
  307. call syscall
  308. jnc .LDOSWRITE1
  309. movw %ax,inoutres;
  310. .LDOSWRITE1:
  311. end;
  312. function do_filepos(handle:longint): longint; assembler;
  313. asm
  314. movw $0x4201,%ax
  315. movl handle,%ebx
  316. xorl %edx,%edx
  317. call syscall
  318. jnc .LDOSFILEPOS
  319. movw %ax,inoutres;
  320. xorl %eax,%eax
  321. .LDOSFILEPOS:
  322. end;
  323. procedure do_seek(handle,pos:longint); assembler;
  324. asm
  325. movw $0x4200,%ax
  326. movl handle,%ebx
  327. movl pos,%edx
  328. call syscall
  329. jnc .LDOSSEEK1
  330. movw %ax,inoutres;
  331. .LDOSSEEK1:
  332. end;
  333. function do_seekend(handle:longint):longint; assembler;
  334. asm
  335. movw $0x4202,%ax
  336. movl handle,%ebx
  337. xorl %edx,%edx
  338. call syscall
  339. jnc .Lset_at_end1
  340. movw %ax,inoutres;
  341. xorl %eax,%eax
  342. .Lset_at_end1:
  343. end;
  344. function do_filesize(handle:longint):longint;
  345. var aktfilepos:longint;
  346. begin
  347. aktfilepos:=do_filepos(handle);
  348. do_filesize:=do_seekend(handle);
  349. do_seek(handle,aktfilepos);
  350. end;
  351. procedure do_truncate(handle,pos:longint); assembler;
  352. asm
  353. (* DOS function 40h isn't safe for this according to EMX documentation
  354. movl $0x4200,%eax
  355. movl handle,%ebx
  356. movl pos,%edx
  357. call syscall
  358. jc .LTruncate1
  359. movl handle,%ebx
  360. movl pos,%edx
  361. movl %ebp,%edx
  362. xorl %ecx,%ecx
  363. movb $0x40,%ah
  364. call syscall
  365. *)
  366. movl $0x7F25,%eax
  367. movl Handle,%ebx
  368. movl Pos,%edx
  369. call syscall
  370. inc %eax
  371. movl %ecx, %eax
  372. jnz .LTruncate1
  373. (* File position is undefined after truncation, move to the end. *)
  374. movl $0x4202,%eax
  375. movl Handle,%ebx
  376. movl $0,%edx
  377. call syscall
  378. jnc .LTruncate2
  379. .LTruncate1:
  380. movw %ax,inoutres;
  381. .LTruncate2:
  382. end;
  383. const
  384. FileHandleCount: longint = 20;
  385. function Increase_File_Handle_Count: boolean;
  386. var Err: word;
  387. L1, L2: longint;
  388. begin
  389. if os_mode = osOS2 then
  390. begin
  391. L1 := 10;
  392. if DosSetRelMaxFH (L1, L2) <> 0 then
  393. Increase_File_Handle_Count := false
  394. else
  395. if L2 > FileHandleCount then
  396. begin
  397. FileHandleCount := L2;
  398. Increase_File_Handle_Count := true;
  399. end
  400. else
  401. Increase_File_Handle_Count := false;
  402. end
  403. else
  404. begin
  405. Inc (FileHandleCount, 10);
  406. Err := 0;
  407. asm
  408. movl $0x6700, %eax
  409. movl FileHandleCount, %ebx
  410. call syscall
  411. jnc .LIncFHandles
  412. movw %ax, Err
  413. .LIncFHandles:
  414. end;
  415. if Err <> 0 then
  416. begin
  417. Increase_File_Handle_Count := false;
  418. Dec (FileHandleCount, 10);
  419. end
  420. else
  421. Increase_File_Handle_Count := true;
  422. end;
  423. end;
  424. procedure do_open(var f;p:pchar;flags:longint);
  425. {
  426. filerec and textrec have both handle and mode as the first items so
  427. they could use the same routine for opening/creating.
  428. when (flags and $100) the file will be append
  429. when (flags and $1000) the file will be truncate/rewritten
  430. when (flags and $10000) there is no check for close (needed for textfiles)
  431. }
  432. var Action: longint;
  433. begin
  434. allowslash(p);
  435. { close first if opened }
  436. if ((flags and $10000)=0) then
  437. begin
  438. case filerec(f).mode of
  439. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  440. fmclosed:;
  441. else
  442. begin
  443. inoutres:=102; {not assigned}
  444. exit;
  445. end;
  446. end;
  447. end;
  448. { reset file handle }
  449. filerec(f).handle := UnusedHandle;
  450. Action := 0;
  451. { convert filemode to filerec modes }
  452. case (flags and 3) of
  453. 0 : filerec(f).mode:=fminput;
  454. 1 : filerec(f).mode:=fmoutput;
  455. 2 : filerec(f).mode:=fminout;
  456. end;
  457. if (flags and $1000)<>0 then
  458. Action := $50000; (* Create / replace *)
  459. { empty name is special }
  460. if p[0]=#0 then
  461. begin
  462. case FileRec(f).mode of
  463. fminput :
  464. FileRec(f).Handle:=StdInputHandle;
  465. fminout, { this is set by rewrite }
  466. fmoutput :
  467. FileRec(f).Handle:=StdOutputHandle;
  468. fmappend :
  469. begin
  470. FileRec(f).Handle:=StdOutputHandle;
  471. FileRec(f).mode:=fmoutput; {fool fmappend}
  472. end;
  473. end;
  474. exit;
  475. end;
  476. Action := Action or (Flags and $FF);
  477. (* DenyAll if sharing not specified. *)
  478. if Flags and 112 = 0 then
  479. Action := Action or 16;
  480. asm
  481. movl $0x7f2b, %eax
  482. movl Action, %ecx
  483. movl p, %edx
  484. call syscall
  485. cmpl $0xffffffff, %eax
  486. jnz .LOPEN1
  487. movw %cx, InOutRes
  488. movw UnusedHandle, %ax
  489. .LOPEN1:
  490. movl f,%edx
  491. movw %ax,(%edx)
  492. end;
  493. if (InOutRes = 4) and Increase_File_Handle_Count then
  494. (* Trying again after increasing amount of file handles *)
  495. asm
  496. movl $0x7f2b, %eax
  497. movl Action, %ecx
  498. movl p, %edx
  499. call syscall
  500. cmpl $0xffffffff, %eax
  501. jnz .LOPEN2
  502. movw %cx, InOutRes
  503. movw UnusedHandle, %ax
  504. .LOPEN2:
  505. movl f,%edx
  506. movw %ax,(%edx)
  507. end;
  508. { for systems that have more handles }
  509. if FileRec (F).Handle > FileHandleCount then
  510. FileHandleCount := FileRec (F).Handle;
  511. if (flags and $100)<>0 then
  512. begin
  513. do_seekend(filerec(f).handle);
  514. FileRec (F).Mode := fmOutput; {fool fmappend}
  515. end;
  516. end;
  517. {$ASMMODE INTEL}
  518. function do_isdevice (Handle: longint): boolean; assembler;
  519. (*
  520. var HT, Attr: longint;
  521. begin
  522. if os_mode = osOS2 then
  523. begin
  524. if DosQueryHType (Handle, HT, Attr) <> 0 then HT := 1;
  525. end
  526. else
  527. *)
  528. asm
  529. mov ebx, Handle
  530. mov eax, 4400h
  531. call syscall
  532. mov eax, 1
  533. jc @IsDevEnd
  534. test edx, 80h
  535. jnz @IsDevEnd
  536. dec eax
  537. @IsDevEnd:
  538. end;
  539. {$ASMMODE ATT}
  540. {*****************************************************************************
  541. UnTyped File Handling
  542. *****************************************************************************}
  543. {$i file.inc}
  544. {*****************************************************************************
  545. Typed File Handling
  546. *****************************************************************************}
  547. {$i typefile.inc}
  548. {*****************************************************************************
  549. Text File Handling
  550. *****************************************************************************}
  551. {$DEFINE EOF_CTRLZ}
  552. {$i text.inc}
  553. {****************************************************************************
  554. Directory related routines.
  555. ****************************************************************************}
  556. {*****************************************************************************
  557. Directory Handling
  558. *****************************************************************************}
  559. procedure dosdir(func:byte;const s:string);
  560. var buffer:array[0..255] of char;
  561. begin
  562. move(s[1],buffer,length(s));
  563. buffer[length(s)]:=#0;
  564. allowslash(Pchar(@buffer));
  565. asm
  566. leal buffer,%edx
  567. movb func,%ah
  568. call syscall
  569. jnc .LDOS_DIRS1
  570. movw %ax,inoutres
  571. .LDOS_DIRS1:
  572. end;
  573. end;
  574. procedure MkDir (const S: string);
  575. begin
  576. If (s='') or (InOutRes <> 0) then
  577. exit;
  578. DosDir ($39, S);
  579. end;
  580. procedure rmdir(const s : string);
  581. begin
  582. If (s='') or (InOutRes <> 0) then
  583. exit;
  584. DosDir ($3A, S);
  585. end;
  586. {$ASMMODE INTEL}
  587. procedure ChDir (const S: string);
  588. var RC: longint;
  589. Buffer: array [0..255] of char;
  590. begin
  591. If (s='') or (InOutRes <> 0) then
  592. exit;
  593. (* According to EMX documentation, EMX has only one current directory
  594. for all processes, so we'll use native calls under OS/2. *)
  595. if os_Mode = osOS2 then
  596. begin
  597. if (Length (S) >= 2) and (S [2] = ':') then
  598. begin
  599. RC := DosSetDefaultDisk ((Ord (S [1]) and
  600. not ($20)) - $40);
  601. if RC <> 0 then
  602. InOutRes := RC
  603. else
  604. if Length (S) > 2 then
  605. begin
  606. Move (S [1], Buffer, Length (S));
  607. Buffer [Length (S)] := #0;
  608. AllowSlash (PChar (@Buffer));
  609. RC := DosSetCurrentDir (@Buffer);
  610. if RC <> 0 then
  611. InOutRes := RC;
  612. end;
  613. end
  614. else
  615. begin
  616. Move (S [1], Buffer, Length (S));
  617. Buffer [Length (S)] := #0;
  618. AllowSlash (PChar (@Buffer));
  619. RC := DosSetCurrentDir (@Buffer);
  620. if RC <> 0 then
  621. InOutRes := RC;
  622. end;
  623. end
  624. else
  625. if (Length (S) >= 2) and (S [2] = ':') then
  626. begin
  627. asm
  628. mov esi, S
  629. mov al, [esi + 1]
  630. and al, not (20h)
  631. sub al, 41h
  632. mov edx, eax
  633. mov ah, 0Eh
  634. call syscall
  635. mov ah, 19h
  636. call syscall
  637. cmp al, dl
  638. jz @LCHDIR
  639. mov InOutRes, 15
  640. @LCHDIR:
  641. end;
  642. if (Length (S) > 2) and (InOutRes <> 0) then
  643. DosDir ($3B, S);
  644. end
  645. else
  646. DosDir ($3B, S);
  647. end;
  648. {$ASMMODE ATT}
  649. procedure GetDir (DriveNr: byte; var Dir: ShortString);
  650. {Written by Michael Van Canneyt.}
  651. var sof:Pchar;
  652. i:byte;
  653. begin
  654. Dir [4] := #0;
  655. { Used in case the specified drive isn't available }
  656. sof:=pchar(@dir[4]);
  657. { dir[1..3] will contain '[drivenr]:\', but is not }
  658. { supplied by DOS, so we let dos string start at }
  659. { dir[4] }
  660. { Get dir from drivenr : 0=default, 1=A etc... }
  661. asm
  662. movb drivenr,%dl
  663. movl sof,%esi
  664. mov $0x47,%ah
  665. call syscall
  666. jnc .LGetDir
  667. movw %ax, InOutRes
  668. .LGetDir:
  669. end;
  670. { Now Dir should be filled with directory in ASCIIZ, }
  671. { starting from dir[4] }
  672. dir[0]:=#3;
  673. dir[2]:=':';
  674. dir[3]:='\';
  675. i:=4;
  676. {Conversion to Pascal string }
  677. while (dir[i]<>#0) do
  678. begin
  679. { convert path name to DOS }
  680. if dir[i]='/' then
  681. dir[i]:='\';
  682. dir[0]:=char(i);
  683. inc(i);
  684. end;
  685. { upcase the string (FPC function) }
  686. if drivenr<>0 then { Drive was supplied. We know it }
  687. dir[1]:=chr(64+drivenr)
  688. else
  689. begin
  690. { We need to get the current drive from DOS function 19H }
  691. { because the drive was the default, which can be unknown }
  692. asm
  693. movb $0x19,%ah
  694. call syscall
  695. addb $65,%al
  696. movb %al,i
  697. end;
  698. dir[1]:=char(i);
  699. end;
  700. if not (FileNameCaseSensitive) then dir:=upcase(dir);
  701. end;
  702. {****************************************************************************
  703. Thread Handling
  704. *****************************************************************************}
  705. const
  706. fpucw: word = $1332;
  707. procedure InitFPU; assembler;
  708. asm
  709. fninit
  710. fldcw fpucw
  711. end;
  712. { include threading stuff, this is os independend part }
  713. {$I thread.inc}
  714. {*****************************************************************************
  715. System unit initialization.
  716. ****************************************************************************}
  717. function GetFileHandleCount: longint;
  718. var L1, L2: longint;
  719. begin
  720. L1 := 0; (* Don't change the amount, just check. *)
  721. if DosSetRelMaxFH (L1, L2) <> 0 then GetFileHandleCount := 50
  722. else GetFileHandleCount := L2;
  723. end;
  724. var tib:Pthreadinfoblock;
  725. begin
  726. {Determine the operating system we are running on.}
  727. {$ASMMODE INTEL}
  728. asm
  729. mov os_mode, 0
  730. mov ax, 7F0Ah
  731. call syscall
  732. test bx, 512 {Bit 9 is OS/2 flag.}
  733. setne byte ptr os_mode
  734. test bx, 4096
  735. jz @noRSX
  736. mov os_mode, 2
  737. @noRSX:
  738. {Enable the brk area by initializing it with the initial heap size.}
  739. mov ax, 7F01h
  740. mov edx, HeapSize
  741. add edx, heap_base
  742. call syscall
  743. cmp eax, -1
  744. jnz @heapok
  745. push dword 204
  746. call HandleError
  747. @heapok:
  748. end;
  749. {Now request, if we are running under DOS,
  750. read-access to the first meg. of memory.}
  751. if os_mode in [osDOS,osDPMI] then
  752. asm
  753. mov ax, 7F13h
  754. xor ebx, ebx
  755. mov ecx, 0FFFh
  756. xor edx, edx
  757. call syscall
  758. mov first_meg, eax
  759. end
  760. else
  761. begin
  762. first_meg := nil;
  763. (* Initialize the amount of file handles *)
  764. FileHandleCount := GetFileHandleCount;
  765. end;
  766. {At 0.9.2, case for enumeration does not work.}
  767. case os_mode of
  768. osDOS:
  769. stackbottom:=0; {In DOS mode, heap_brk is also the
  770. stack bottom.}
  771. osOS2:
  772. begin
  773. dosgetinfoblocks(@tib,nil);
  774. stackbottom:=longint(tib^.stack);
  775. end;
  776. osDPMI:
  777. stackbottom:=0; {Not sure how to get it, but seems to be
  778. always zero.}
  779. end;
  780. exitproc:=nil;
  781. {$ifdef MT}
  782. if os_mode = osOS2 then
  783. begin
  784. { allocate one ThreadVar entry from the OS, we use this entry }
  785. { for a pointer to our threadvars }
  786. if DosAllocThreadLocalMemory (1, DataIndex) <> 0 then RunError (8);
  787. { the exceptions use threadvars so do this _before_ initexceptions }
  788. AllocateThreadVars;
  789. end;
  790. {$endif MT}
  791. {Initialize the heap.}
  792. initheap;
  793. { ... and exceptions }
  794. InitExceptions;
  795. { to test stack depth }
  796. loweststack:=maxlongint;
  797. OpenStdIO(Input,fmInput,StdInputHandle);
  798. OpenStdIO(Output,fmOutput,StdOutputHandle);
  799. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  800. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  801. { no I/O-Error }
  802. inoutres:=0;
  803. end.
  804. {
  805. $Log$
  806. Revision 1.12 2001-04-20 19:05:11 hajny
  807. * setne operand size fixed
  808. Revision 1.11 2001/03/21 23:29:40 florian
  809. + sLineBreak and misc. stuff for Kylix compatiblity
  810. Revision 1.10 2001/03/21 21:08:20 hajny
  811. * GetDir fixed
  812. Revision 1.9 2001/03/10 09:57:51 hajny
  813. * FExpand without IOResult change, remaining direct asm removed
  814. Revision 1.8 2001/02/20 21:31:12 peter
  815. * chdir,mkdir,rmdir with empty string fixed
  816. Revision 1.7 2001/02/04 01:57:52 hajny
  817. * direct asm removing
  818. Revision 1.6 2001/02/01 21:30:01 hajny
  819. * MT support completion
  820. Revision 1.5 2001/01/23 20:38:59 hajny
  821. + beginning of the OS/2 version
  822. Revision 1.4 2000/11/13 21:23:38 hajny
  823. * ParamStr (0) fixed
  824. Revision 1.3 2000/11/11 23:12:39 hajny
  825. * stackcheck alias corrected
  826. Revision 1.2 2000/10/15 20:43:10 hajny
  827. * ChDir correction, unit name changed
  828. Revision 1.1 2000/10/15 08:19:49 peter
  829. * system unit rename for 1.1 branch
  830. Revision 1.3 2000/09/29 21:49:41 jonas
  831. * removed warnings
  832. Revision 1.2 2000/07/14 10:33:11 michael
  833. + Conditionals fixed
  834. Revision 1.1 2000/07/13 06:31:07 michael
  835. + Initial import
  836. }