system.pas 30 KB

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