system.pas 30 KB

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