system.pas 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  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. TRTLCriticalSection = 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. {Platform specific information}
  62. const
  63. LineEnding = #13#10;
  64. { LFNSupport is defined separately below!!! }
  65. DirectorySeparator = '\';
  66. DriveSeparator = ':';
  67. PathSeparator = ';';
  68. { FileNameCaseSensitive is defined separately below!!! }
  69. type Tos=(osDOS,osOS2,osDPMI);
  70. var os_mode:Tos;
  71. first_meg:pointer;
  72. type Psysthreadib=^Tsysthreadib;
  73. Pthreadinfoblock=^Tthreadinfoblock;
  74. PPThreadInfoBlock=^PThreadInfoBlock;
  75. Pprocessinfoblock=^Tprocessinfoblock;
  76. PPProcessInfoBlock=^PProcessInfoBlock;
  77. Tbytearray=array[0..$ffff] of byte;
  78. Pbytearray=^Tbytearray;
  79. Tsysthreadib=record
  80. tid,
  81. priority,
  82. version:longint;
  83. MCcount,
  84. MCforceflag:word;
  85. end;
  86. Tthreadinfoblock=record
  87. pexchain,
  88. stack,
  89. stacklimit:pointer;
  90. tib2:Psysthreadib;
  91. version,
  92. ordinal:longint;
  93. end;
  94. Tprocessinfoblock=record
  95. pid,
  96. parentpid,
  97. hmte:longint;
  98. cmd,
  99. env:Pbytearray;
  100. flstatus,
  101. ttype:longint;
  102. end;
  103. const UnusedHandle=$ffff;
  104. StdInputHandle=0;
  105. StdOutputHandle=1;
  106. StdErrorHandle=2;
  107. LFNSupport: boolean = true;
  108. FileNameCaseSensitive: boolean = false;
  109. sLineBreak : string[2] = LineEnding;
  110. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF;
  111. var
  112. { C-compatible arguments and environment }
  113. argc : longint;external name '_argc';
  114. argv : ppchar;external name '_argv';
  115. envp : ppchar;external name '_environ';
  116. implementation
  117. {$I SYSTEM.INC}
  118. var
  119. heap_base: pointer; external name '__heap_base';
  120. heap_brk: pointer; external name '__heap_brk';
  121. heap_end: pointer; external name '__heap_end';
  122. procedure DosGetInfoBlocks (PATIB: PPThreadInfoBlock;
  123. PAPIB: PPProcessInfoBlock); cdecl;
  124. external 'DOSCALLS' index 312;
  125. function DosSetRelMaxFH (var ReqCount, CurMaxFH: longint): longint; cdecl;
  126. external 'DOSCALLS' index 382;
  127. function DosSetCurrentDir (Name:PChar): longint; cdecl;
  128. external 'DOSCALLS' index 255;
  129. function DosSetDefaultDisk (DiskNum:longint): longint; cdecl;
  130. external 'DOSCALLS' index 220;
  131. { This is not real prototype, but its close enough }
  132. { for us. (The 2nd parameter is acutally a pointer) }
  133. { to a structure. }
  134. function DosCreateDir( Name : pchar; p : pointer): longint; cdecl;
  135. external 'DOSCALLS' index 270;
  136. function DosDeleteDir( Name : pchar) : longint; cdecl;
  137. external 'DOSCALLS' index 226;
  138. {This is the correct way to call external assembler procedures.}
  139. procedure syscall; external name '___SYSCALL';
  140. {
  141. procedure syscall; external 'EMX' index 2;
  142. procedure emx_init; external 'EMX' index 1;
  143. }
  144. { converts an OS/2 error code to a TP compatible error }
  145. { code. Same thing exists under most other supported }
  146. { systems. }
  147. { Only call for OS/2 DLL imported routines }
  148. Procedure Errno2InOutRes;
  149. Begin
  150. { errors 1..18 are the same as in DOS }
  151. case InOutRes of
  152. { simple offset to convert these error codes }
  153. { exactly like the error codes in Win32 }
  154. 19..31 : InOutRes := InOutRes + 131;
  155. { gets a bit more complicated ... }
  156. 32..33 : InOutRes := 5;
  157. 38 : InOutRes := 100;
  158. 39 : InOutRes := 101;
  159. 112 : InOutRes := 101;
  160. 110 : InOutRes := 5;
  161. 114 : InOutRes := 6;
  162. 290 : InOutRes := 290;
  163. end;
  164. { all other cases ... we keep the same error code }
  165. end;
  166. {****************************************************************************
  167. Miscellaneous related routines.
  168. ****************************************************************************}
  169. {$asmmode intel}
  170. procedure system_exit; assembler;
  171. asm
  172. mov ah, 04ch
  173. mov al, byte ptr exitcode
  174. call syscall
  175. end ['EAX'];
  176. {$ASMMODE ATT}
  177. function paramcount:longint;assembler;
  178. asm
  179. movl argc,%eax
  180. decl %eax
  181. end ['EAX'];
  182. function args:pointer;assembler;
  183. asm
  184. movl argv,%eax
  185. end ['EAX'];
  186. function paramstr(l:longint):string;
  187. var p:^Pchar;
  188. begin
  189. { There seems to be a problem with EMX for DOS when trying to }
  190. { access paramstr(0), and to avoid problems between DOS and }
  191. { OS/2 they have been separated. }
  192. if os_Mode = OsOs2 then
  193. begin
  194. if L = 0 then
  195. begin
  196. GetMem (P, 260);
  197. p[0] := #0; { in case of error, initialize to empty string }
  198. {$ASMMODE INTEL}
  199. asm
  200. mov edx, P
  201. mov ecx, 260
  202. mov eax, 7F33h
  203. call syscall { error handle already with empty string }
  204. end;
  205. ParamStr := StrPas (PChar (P));
  206. FreeMem (P, 260);
  207. end
  208. else
  209. if (l>0) and (l<=paramcount) then
  210. begin
  211. p:=args;
  212. paramstr:=strpas(p[l]);
  213. end
  214. else paramstr:='';
  215. end
  216. else
  217. begin
  218. p:=args;
  219. paramstr:=strpas(p[l]);
  220. end;
  221. end;
  222. procedure randomize; assembler;
  223. asm
  224. mov ah, 2Ch
  225. call syscall
  226. mov word ptr [randseed], cx
  227. mov word ptr [randseed + 2], dx
  228. end;
  229. {$ASMMODE ATT}
  230. {****************************************************************************
  231. Heap management releated routines.
  232. ****************************************************************************}
  233. { this function allows to extend the heap by calling
  234. syscall $7f00 resizes the brk area}
  235. function sbrk(size:longint):longint; assembler;
  236. asm
  237. movl size,%edx
  238. movw $0x7f00,%ax
  239. call syscall { result directly in EAX }
  240. end;
  241. function getheapstart:pointer;assembler;
  242. asm
  243. movl heap_base,%eax
  244. end ['EAX'];
  245. function getheapsize:longint;assembler;
  246. asm
  247. movl heap_brk,%eax
  248. end ['EAX'];
  249. {$i heap.inc}
  250. {****************************************************************************
  251. Low Level File Routines
  252. ****************************************************************************}
  253. procedure allowslash(p:Pchar);
  254. {Allow slash as backslash.}
  255. var i:longint;
  256. begin
  257. for i:=0 to strlen(p) do
  258. if p[i]='/' then p[i]:='\';
  259. end;
  260. procedure do_close(h:longint);
  261. begin
  262. { Only three standard handles under real OS/2 }
  263. if (h > 4) or
  264. ((os_MODE = osOS2) and (h > 2)) then
  265. begin
  266. asm
  267. movb $0x3e,%ah
  268. movl h,%ebx
  269. call syscall
  270. jnc .Lnoerror { error code? }
  271. movw %ax, InOutRes { yes, then set InOutRes }
  272. .Lnoerror:
  273. end;
  274. end;
  275. end;
  276. procedure do_erase(p:Pchar);
  277. begin
  278. allowslash(p);
  279. asm
  280. movl P,%edx
  281. movb $0x41,%ah
  282. call syscall
  283. jnc .LERASE1
  284. movw %ax,inoutres;
  285. .LERASE1:
  286. end;
  287. end;
  288. procedure do_rename(p1,p2:Pchar);
  289. begin
  290. allowslash(p1);
  291. allowslash(p2);
  292. asm
  293. movl P1, %edx
  294. movl P2, %edi
  295. movb $0x56,%ah
  296. call syscall
  297. jnc .LRENAME1
  298. movw %ax,inoutres;
  299. .LRENAME1:
  300. end;
  301. end;
  302. function do_read(h,addr,len:longint):longint; assembler;
  303. asm
  304. movl len,%ecx
  305. movl addr,%edx
  306. movl h,%ebx
  307. movb $0x3f,%ah
  308. call syscall
  309. jnc .LDOSREAD1
  310. movw %ax,inoutres;
  311. xorl %eax,%eax
  312. .LDOSREAD1:
  313. end;
  314. function do_write(h,addr,len:longint) : longint; assembler;
  315. asm
  316. xorl %eax,%eax
  317. cmpl $0,len { 0 bytes to write is undefined behavior }
  318. jz .LDOSWRITE1
  319. movl len,%ecx
  320. movl addr,%edx
  321. movl h,%ebx
  322. movb $0x40,%ah
  323. call syscall
  324. jnc .LDOSWRITE1
  325. movw %ax,inoutres;
  326. .LDOSWRITE1:
  327. end;
  328. function do_filepos(handle:longint): longint; assembler;
  329. asm
  330. movw $0x4201,%ax
  331. movl handle,%ebx
  332. xorl %edx,%edx
  333. call syscall
  334. jnc .LDOSFILEPOS
  335. movw %ax,inoutres;
  336. xorl %eax,%eax
  337. .LDOSFILEPOS:
  338. end;
  339. procedure do_seek(handle,pos:longint); assembler;
  340. asm
  341. movw $0x4200,%ax
  342. movl handle,%ebx
  343. movl pos,%edx
  344. call syscall
  345. jnc .LDOSSEEK1
  346. movw %ax,inoutres;
  347. .LDOSSEEK1:
  348. end;
  349. function do_seekend(handle:longint):longint; assembler;
  350. asm
  351. movw $0x4202,%ax
  352. movl handle,%ebx
  353. xorl %edx,%edx
  354. call syscall
  355. jnc .Lset_at_end1
  356. movw %ax,inoutres;
  357. xorl %eax,%eax
  358. .Lset_at_end1:
  359. end;
  360. function do_filesize(handle:longint):longint;
  361. var aktfilepos:longint;
  362. begin
  363. aktfilepos:=do_filepos(handle);
  364. do_filesize:=do_seekend(handle);
  365. do_seek(handle,aktfilepos);
  366. end;
  367. procedure do_truncate(handle,pos:longint); assembler;
  368. asm
  369. (* DOS function 40h isn't safe for this according to EMX documentation *)
  370. movl $0x7F25,%eax
  371. movl Handle,%ebx
  372. movl Pos,%edx
  373. call syscall
  374. incl %eax
  375. movl %ecx, %eax
  376. jnz .LTruncate1 { compare the value of EAX to verify error }
  377. (* File position is undefined after truncation, move to the end. *)
  378. movl $0x4202,%eax
  379. movl Handle,%ebx
  380. movl $0,%edx
  381. call syscall
  382. jnc .LTruncate2
  383. .LTruncate1:
  384. movw %ax,inoutres;
  385. .LTruncate2:
  386. end;
  387. const
  388. FileHandleCount: longint = 20;
  389. function Increase_File_Handle_Count: boolean;
  390. var Err: word;
  391. L1, L2: longint;
  392. begin
  393. if os_mode = osOS2 then
  394. begin
  395. L1 := 10;
  396. if DosSetRelMaxFH (L1, L2) <> 0 then
  397. Increase_File_Handle_Count := false
  398. else
  399. if L2 > FileHandleCount then
  400. begin
  401. FileHandleCount := L2;
  402. Increase_File_Handle_Count := true;
  403. end
  404. else
  405. Increase_File_Handle_Count := false;
  406. end
  407. else
  408. begin
  409. Inc (FileHandleCount, 10);
  410. Err := 0;
  411. asm
  412. movl $0x6700, %eax
  413. movl FileHandleCount, %ebx
  414. call syscall
  415. jnc .LIncFHandles
  416. movw %ax, Err
  417. .LIncFHandles:
  418. end;
  419. if Err <> 0 then
  420. begin
  421. Increase_File_Handle_Count := false;
  422. Dec (FileHandleCount, 10);
  423. end
  424. else
  425. Increase_File_Handle_Count := true;
  426. end;
  427. end;
  428. procedure do_open(var f;p:pchar;flags:longint);
  429. {
  430. filerec and textrec have both handle and mode as the first items so
  431. they could use the same routine for opening/creating.
  432. when (flags and $100) the file will be append
  433. when (flags and $1000) the file will be truncate/rewritten
  434. when (flags and $10000) there is no check for close (needed for textfiles)
  435. }
  436. var Action: longint;
  437. begin
  438. allowslash(p);
  439. { close first if opened }
  440. if ((flags and $10000)=0) then
  441. begin
  442. case filerec(f).mode of
  443. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  444. fmclosed:;
  445. else
  446. begin
  447. inoutres:=102; {not assigned}
  448. exit;
  449. end;
  450. end;
  451. end;
  452. { reset file handle }
  453. filerec(f).handle := UnusedHandle;
  454. Action := 0;
  455. { convert filemode to filerec modes }
  456. case (flags and 3) of
  457. 0 : filerec(f).mode:=fminput;
  458. 1 : filerec(f).mode:=fmoutput;
  459. 2 : filerec(f).mode:=fminout;
  460. end;
  461. if (flags and $1000)<>0 then
  462. Action := $50000; (* Create / replace *)
  463. { empty name is special }
  464. if p[0]=#0 then
  465. begin
  466. case FileRec(f).mode of
  467. fminput :
  468. FileRec(f).Handle:=StdInputHandle;
  469. fminout, { this is set by rewrite }
  470. fmoutput :
  471. FileRec(f).Handle:=StdOutputHandle;
  472. fmappend :
  473. begin
  474. FileRec(f).Handle:=StdOutputHandle;
  475. FileRec(f).mode:=fmoutput; {fool fmappend}
  476. end;
  477. end;
  478. exit;
  479. end;
  480. Action := Action or (Flags and $FF);
  481. (* DenyAll if sharing not specified. *)
  482. if Flags and 112 = 0 then
  483. Action := Action or 16;
  484. asm
  485. movl $0x7f2b, %eax
  486. movl Action, %ecx
  487. movl p, %edx
  488. call syscall
  489. cmpl $0xffffffff, %eax
  490. jnz .LOPEN1
  491. movw %cx, InOutRes
  492. movw UnusedHandle, %ax
  493. .LOPEN1:
  494. movl f,%edx { Warning : This assumes Handle is first }
  495. movw %ax,(%edx) { field of FileRec }
  496. end;
  497. if (InOutRes = 4) and Increase_File_Handle_Count then
  498. (* Trying again after increasing amount of file handles *)
  499. asm
  500. movl $0x7f2b, %eax
  501. movl Action, %ecx
  502. movl p, %edx
  503. call syscall
  504. cmpl $0xffffffff, %eax
  505. jnz .LOPEN2
  506. movw %cx, InOutRes
  507. movw UnusedHandle, %ax
  508. .LOPEN2:
  509. movl f,%edx
  510. movw %ax,(%edx)
  511. end;
  512. { for systems that have more handles }
  513. if FileRec (F).Handle > FileHandleCount then
  514. FileHandleCount := FileRec (F).Handle;
  515. if (flags and $100)<>0 then
  516. begin
  517. do_seekend(filerec(f).handle);
  518. FileRec (F).Mode := fmOutput; {fool fmappend}
  519. end;
  520. end;
  521. {$ASMMODE INTEL}
  522. function do_isdevice (Handle: longint): boolean; assembler;
  523. (*
  524. var HT, Attr: longint;
  525. begin
  526. if os_mode = osOS2 then
  527. begin
  528. if DosQueryHType (Handle, HT, Attr) <> 0 then HT := 1;
  529. end
  530. else
  531. *)
  532. asm
  533. mov ebx, Handle
  534. mov eax, 4400h
  535. call syscall
  536. mov eax, 1
  537. jc @IsDevEnd
  538. test edx, 80h { verify if it is a file }
  539. jnz @IsDevEnd
  540. dec eax { nope, so result is zero }
  541. @IsDevEnd:
  542. end;
  543. {$ASMMODE ATT}
  544. {*****************************************************************************
  545. UnTyped File Handling
  546. *****************************************************************************}
  547. {$i file.inc}
  548. {*****************************************************************************
  549. Typed File Handling
  550. *****************************************************************************}
  551. {$i typefile.inc}
  552. {*****************************************************************************
  553. Text File Handling
  554. *****************************************************************************}
  555. {$DEFINE EOF_CTRLZ}
  556. {$i text.inc}
  557. {****************************************************************************
  558. Directory related routines.
  559. ****************************************************************************}
  560. {*****************************************************************************
  561. Directory Handling
  562. *****************************************************************************}
  563. procedure dosdir(func:byte;const s:string);
  564. var buffer:array[0..255] of char;
  565. begin
  566. move(s[1],buffer,length(s));
  567. buffer[length(s)]:=#0;
  568. allowslash(Pchar(@buffer));
  569. asm
  570. leal buffer,%edx
  571. movb func,%ah
  572. call syscall
  573. jnc .LDOS_DIRS1
  574. movw %ax,inoutres
  575. .LDOS_DIRS1:
  576. end;
  577. end;
  578. procedure MkDir (const S: string);[IOCHECK];
  579. var buffer:array[0..255] of char;
  580. Rc : word;
  581. begin
  582. If (s='') or (InOutRes <> 0) then
  583. exit;
  584. if os_mode = osOs2 then
  585. begin
  586. move(s[1],buffer,length(s));
  587. buffer[length(s)]:=#0;
  588. allowslash(Pchar(@buffer));
  589. Rc := DosCreateDir(buffer,nil);
  590. if Rc <> 0 then
  591. begin
  592. InOutRes := Rc;
  593. Errno2Inoutres;
  594. end;
  595. end
  596. else
  597. begin
  598. { Under EMX 0.9d DOS this routine call may sometimes fail }
  599. { The syscall documentation indicates clearly that this }
  600. { routine was NOT tested. }
  601. DosDir ($39, S);
  602. end;
  603. end;
  604. procedure rmdir(const s : string);[IOCHECK];
  605. var buffer:array[0..255] of char;
  606. Rc : word;
  607. begin
  608. if (s = '.' ) then
  609. InOutRes := 16;
  610. If (s='') or (InOutRes <> 0) then
  611. exit;
  612. if os_mode = osOs2 then
  613. begin
  614. move(s[1],buffer,length(s));
  615. buffer[length(s)]:=#0;
  616. allowslash(Pchar(@buffer));
  617. Rc := DosDeleteDir(buffer);
  618. if Rc <> 0 then
  619. begin
  620. InOutRes := Rc;
  621. Errno2Inoutres;
  622. end;
  623. end
  624. else
  625. begin
  626. { Under EMX 0.9d DOS this routine call may sometimes fail }
  627. { The syscall documentation indicates clearly that this }
  628. { routine was NOT tested. }
  629. DosDir ($3A, S);
  630. end;
  631. end;
  632. {$ASMMODE INTEL}
  633. procedure ChDir (const S: string);[IOCheck];
  634. var RC: longint;
  635. Buffer: array [0..255] of char;
  636. begin
  637. If (s='') or (InOutRes <> 0) then
  638. exit;
  639. (* According to EMX documentation, EMX has only one current directory
  640. for all processes, so we'll use native calls under OS/2. *)
  641. if os_Mode = osOS2 then
  642. begin
  643. if (Length (S) >= 2) and (S [2] = ':') then
  644. begin
  645. RC := DosSetDefaultDisk ((Ord (S [1]) and
  646. not ($20)) - $40);
  647. if RC <> 0 then
  648. InOutRes := RC
  649. else
  650. if Length (S) > 2 then
  651. begin
  652. Move (S [1], Buffer, Length (S));
  653. Buffer [Length (S)] := #0;
  654. AllowSlash (PChar (@Buffer));
  655. RC := DosSetCurrentDir (@Buffer);
  656. if RC <> 0 then
  657. begin
  658. InOutRes := RC;
  659. Errno2InOutRes;
  660. end;
  661. end;
  662. end
  663. else
  664. begin
  665. Move (S [1], Buffer, Length (S));
  666. Buffer [Length (S)] := #0;
  667. AllowSlash (PChar (@Buffer));
  668. RC := DosSetCurrentDir (@Buffer);
  669. if RC <> 0 then
  670. begin
  671. InOutRes:= RC;
  672. Errno2InOutRes;
  673. end;
  674. end;
  675. end
  676. else
  677. if (Length (S) >= 2) and (S [2] = ':') then
  678. begin
  679. asm
  680. mov esi, S
  681. mov al, [esi + 1]
  682. and al, not (20h)
  683. sub al, 41h
  684. mov edx, eax
  685. mov ah, 0Eh
  686. call syscall
  687. mov ah, 19h
  688. call syscall
  689. cmp al, dl
  690. jz @LCHDIR
  691. mov InOutRes, 15
  692. @LCHDIR:
  693. end;
  694. if (Length (S) > 2) and (InOutRes <> 0) then
  695. { Under EMX 0.9d DOS this routine may sometime }
  696. { fail or crash the system. }
  697. DosDir ($3B, S);
  698. end
  699. else
  700. { Under EMX 0.9d DOS this routine may sometime }
  701. { fail or crash the system. }
  702. DosDir ($3B, S);
  703. end;
  704. {$ASMMODE ATT}
  705. procedure GetDir (DriveNr: byte; var Dir: ShortString);
  706. {Written by Michael Van Canneyt.}
  707. var sof:Pchar;
  708. i:byte;
  709. begin
  710. Dir [4] := #0;
  711. { Used in case the specified drive isn't available }
  712. sof:=pchar(@dir[4]);
  713. { dir[1..3] will contain '[drivenr]:\', but is not }
  714. { supplied by DOS, so we let dos string start at }
  715. { dir[4] }
  716. { Get dir from drivenr : 0=default, 1=A etc... }
  717. asm
  718. movb drivenr,%dl
  719. movl sof,%esi
  720. mov $0x47,%ah
  721. call syscall
  722. jnc .LGetDir
  723. movw %ax, InOutRes
  724. .LGetDir:
  725. end;
  726. { Now Dir should be filled with directory in ASCIIZ, }
  727. { starting from dir[4] }
  728. dir[0]:=#3;
  729. dir[2]:=':';
  730. dir[3]:='\';
  731. i:=4;
  732. {Conversion to Pascal string }
  733. while (dir[i]<>#0) do
  734. begin
  735. { convert path name to DOS }
  736. if dir[i]='/' then
  737. dir[i]:='\';
  738. dir[0]:=char(i);
  739. inc(i);
  740. end;
  741. { upcase the string (FPC function) }
  742. if drivenr<>0 then { Drive was supplied. We know it }
  743. dir[1]:=chr(64+drivenr)
  744. else
  745. begin
  746. { We need to get the current drive from DOS function 19H }
  747. { because the drive was the default, which can be unknown }
  748. asm
  749. movb $0x19,%ah
  750. call syscall
  751. addb $65,%al
  752. movb %al,i
  753. end;
  754. dir[1]:=char(i);
  755. end;
  756. if not (FileNameCaseSensitive) then dir:=upcase(dir);
  757. end;
  758. {****************************************************************************
  759. Thread Handling
  760. *****************************************************************************}
  761. const
  762. fpucw: word = $1332;
  763. procedure InitFPU; assembler;
  764. asm
  765. fninit
  766. fldcw fpucw
  767. end;
  768. { include threading stuff, this is os independend part }
  769. {$I thread.inc}
  770. {*****************************************************************************
  771. System unit initialization.
  772. ****************************************************************************}
  773. function GetFileHandleCount: longint;
  774. var L1, L2: longint;
  775. begin
  776. L1 := 0; (* Don't change the amount, just check. *)
  777. if DosSetRelMaxFH (L1, L2) <> 0 then GetFileHandleCount := 50
  778. else GetFileHandleCount := L2;
  779. end;
  780. var tib:Pthreadinfoblock;
  781. begin
  782. {Determine the operating system we are running on.}
  783. {$ASMMODE INTEL}
  784. asm
  785. mov os_mode, 0
  786. mov ax, 7F0Ah
  787. call syscall
  788. test bx, 512 {Bit 9 is OS/2 flag.}
  789. setne byte ptr os_mode
  790. test bx, 4096
  791. jz @noRSX
  792. mov os_mode, 2
  793. @noRSX:
  794. {Enable the brk area by initializing it with the initial heap size.}
  795. mov ax, 7F01h
  796. mov edx, heap_brk
  797. add edx, heap_base
  798. call syscall
  799. cmp eax, -1
  800. jnz @heapok
  801. push dword 204
  802. call HandleError
  803. @heapok:
  804. end;
  805. { in OS/2 this will always be nil, but in DOS mode }
  806. { this can be changed. }
  807. first_meg := nil;
  808. {Now request, if we are running under DOS,
  809. read-access to the first meg. of memory.}
  810. if os_mode in [osDOS,osDPMI] then
  811. asm
  812. mov ax, 7F13h
  813. xor ebx, ebx
  814. mov ecx, 0FFFh
  815. xor edx, edx
  816. call syscall
  817. jnc @endmem
  818. mov first_meg, eax
  819. @endmem:
  820. end
  821. else
  822. begin
  823. (* Initialize the amount of file handles *)
  824. FileHandleCount := GetFileHandleCount;
  825. end;
  826. {At 0.9.2, case for enumeration does not work.}
  827. case os_mode of
  828. osDOS:
  829. stackbottom:=cardinal(heap_brk); {In DOS mode, heap_brk is also the
  830. stack bottom.}
  831. osOS2:
  832. begin
  833. dosgetinfoblocks(@tib,nil);
  834. stackbottom:=cardinal(tib^.stack);
  835. end;
  836. osDPMI:
  837. stackbottom:=0; {Not sure how to get it, but seems to be
  838. always zero.}
  839. end;
  840. exitproc:=nil;
  841. {$ifdef MT}
  842. if os_mode = osOS2 then
  843. begin
  844. { allocate one ThreadVar entry from the OS, we use this entry }
  845. { for a pointer to our threadvars }
  846. if DosAllocThreadLocalMemory (1, DataIndex) <> 0 then RunError (8);
  847. { the exceptions use threadvars so do this _before_ initexceptions }
  848. AllocateThreadVars;
  849. end;
  850. {$endif MT}
  851. {Initialize the heap.}
  852. initheap;
  853. { ... and exceptions }
  854. InitExceptions;
  855. OpenStdIO(Input,fmInput,StdInputHandle);
  856. OpenStdIO(Output,fmOutput,StdOutputHandle);
  857. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  858. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  859. { no I/O-Error }
  860. inoutres:=0;
  861. end.
  862. {
  863. $Log$
  864. Revision 1.20 2002-04-12 17:42:16 carl
  865. + generic stack checking
  866. Revision 1.19 2002/03/11 19:10:33 peter
  867. * Regenerated with updated fpcmake
  868. Revision 1.18 2002/02/10 13:46:20 hajny
  869. * heap management corrected (heap_brk)
  870. Revision 1.17 2001/11/15 18:49:43 hajny
  871. * DefaultTextLineBreakStyle misplacing corrected
  872. Revision 1.16 2001/10/23 21:51:03 peter
  873. * criticalsection renamed to rtlcriticalsection for kylix compatibility
  874. Revision 1.15 2001/06/19 20:46:07 hajny
  875. * platform specific constants moved after systemh.inc, BeOS omission corrected
  876. Revision 1.14 2001/06/13 22:21:53 hajny
  877. + platform specific information
  878. Revision 1.13 2001/05/20 18:40:32 hajny
  879. * merging Carl's fixes from the fixes branch
  880. Revision 1.12 2001/04/20 19:05:11 hajny
  881. * setne operand size fixed
  882. Revision 1.11 2001/03/21 23:29:40 florian
  883. + sLineBreak and misc. stuff for Kylix compatiblity
  884. Revision 1.10 2001/03/21 21:08:20 hajny
  885. * GetDir fixed
  886. Revision 1.9 2001/03/10 09:57:51 hajny
  887. * FExpand without IOResult change, remaining direct asm removed
  888. Revision 1.8 2001/02/20 21:31:12 peter
  889. * chdir,mkdir,rmdir with empty string fixed
  890. Revision 1.7 2001/02/04 01:57:52 hajny
  891. * direct asm removing
  892. Revision 1.6 2001/02/01 21:30:01 hajny
  893. * MT support completion
  894. Revision 1.5 2001/01/23 20:38:59 hajny
  895. + beginning of the OS/2 version
  896. Revision 1.4 2000/11/13 21:23:38 hajny
  897. * ParamStr (0) fixed
  898. Revision 1.3 2000/11/11 23:12:39 hajny
  899. * stackcheck alias corrected
  900. Revision 1.2 2000/10/15 20:43:10 hajny
  901. * ChDir correction, unit name changed
  902. Revision 1.1 2000/10/15 08:19:49 peter
  903. * system unit rename for 1.1 branch
  904. Revision 1.3 2000/09/29 21:49:41 jonas
  905. * removed warnings
  906. Revision 1.2 2000/07/14 10:33:11 michael
  907. + Conditionals fixed
  908. Revision 1.1 2000/07/13 06:31:07 michael
  909. + Initial import
  910. }