system.pas 27 KB

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