system.pas 25 KB

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