system.pas 29 KB

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