system.pas 24 KB

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