sysutils.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. Sysutils unit for OS/2
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. unit sysutils;
  14. interface
  15. {$MODE objfpc}
  16. { force ansistrings }
  17. {$H+}
  18. uses
  19. doscalls,dos;
  20. { Include platform independent interface part }
  21. {$i sysutilh.inc}
  22. implementation
  23. { Include platform independent implementation part }
  24. {$i sysutils.inc}
  25. {****************************************************************************
  26. File Functions
  27. ****************************************************************************}
  28. {This is the correct way to call external assembler procedures.}
  29. procedure syscall;external name '___SYSCALL';
  30. const
  31. ofRead = $0000; {Open for reading}
  32. ofWrite = $0001; {Open for writing}
  33. ofReadWrite = $0002; {Open for reading/writing}
  34. faCreateNew = $00010000; {Create if file does not exist}
  35. faOpenReplace = $00040000; {Truncate if file exists}
  36. faCreate = $00050000; {Create if file does not exist, truncate otherwise}
  37. {$ASMMODE INTEL}
  38. function FileOpen (const FileName: string; Mode: integer): longint;
  39. {$IFOPT H+}
  40. assembler;
  41. {$ELSE}
  42. var FN: string;
  43. begin
  44. FN := FileName + #0;
  45. {$ENDIF}
  46. asm
  47. mov eax, Mode
  48. (* DenyAll if sharing not specified. *)
  49. test eax, 112
  50. jnz @FOpen1
  51. or eax, 16
  52. @FOpen1:
  53. mov ecx, eax
  54. mov eax, 7F2Bh
  55. {$IFOPT H+}
  56. mov edx, FileName
  57. {$ELSE}
  58. lea edx, FN
  59. inc edx
  60. {$ENDIF}
  61. call syscall
  62. {$IFOPT H-}
  63. mov [ebp - 4], eax
  64. end;
  65. {$ENDIF}
  66. end;
  67. function FileCreate (const FileName: string): longint;
  68. {$IFOPT H+}
  69. assembler;
  70. {$ELSE}
  71. var FN: string;
  72. begin
  73. FN := FileName + #0;
  74. {$ENDIF}
  75. asm
  76. mov eax, 7F2Bh
  77. mov ecx, ofReadWrite or faCreate
  78. {$IFOPT H+}
  79. mov edx, FileName
  80. {$ELSE}
  81. lea edx, FN
  82. inc edx
  83. {$ENDIF}
  84. call syscall
  85. {$IFOPT H-}
  86. mov [ebp - 4], eax
  87. end;
  88. {$ENDIF}
  89. end;
  90. function FileRead (Handle: longint; var Buffer; Count: longint): longint;
  91. assembler;
  92. asm
  93. mov eax, 3F00h
  94. mov ebx, Handle
  95. mov ecx, Count
  96. mov edx, Buffer
  97. call syscall
  98. jnc @FReadEnd
  99. mov eax, -1
  100. @FReadEnd:
  101. end;
  102. function FileWrite (Handle: longint; const Buffer; Count: longint): longint;
  103. assembler;
  104. asm
  105. mov eax, 4000h
  106. mov ebx, Handle
  107. mov ecx, Count
  108. mov edx, Buffer
  109. call syscall
  110. jnc @FWriteEnd
  111. mov eax, -1
  112. @FWriteEnd:
  113. end;
  114. function FileSeek (Handle, FOffset, Origin: longint): longint; assembler;
  115. asm
  116. mov eax, Origin
  117. mov ah, 42h
  118. mov ebx, Handle
  119. mov edx, FOffset
  120. call syscall
  121. jnc @FSeekEnd
  122. mov eax, -1
  123. @FSeekEnd:
  124. end;
  125. procedure FileClose (Handle: longint);
  126. begin
  127. if (Handle <= 4) or (os_mode = osOS2) and (Handle <= 2) then
  128. asm
  129. mov eax, 3E00h
  130. mov ebx, Handle
  131. call syscall
  132. end;
  133. end;
  134. function FileTruncate (Handle, Size: longint): boolean; assembler;
  135. asm
  136. mov eax, 7F25h
  137. mov ebx, Handle
  138. mov edx, Size
  139. call syscall
  140. jc @FTruncEnd
  141. mov eax, 4202h
  142. mov ebx, Handle
  143. mov edx, 0
  144. call syscall
  145. mov eax, 0
  146. jnc @FTruncEnd
  147. dec eax
  148. @FTruncEnd:
  149. end;
  150. function FileAge (const FileName: string): longint;
  151. var Handle: longint;
  152. begin
  153. Handle := FileOpen (FileName, 0);
  154. if Handle <> -1 then
  155. begin
  156. Result := FileGetDate (Handle);
  157. FileClose (Handle);
  158. end
  159. else
  160. Result := -1;
  161. end;
  162. function FileExists (const FileName: string): boolean;
  163. {$IFOPT H+}
  164. assembler;
  165. {$ELSE}
  166. var FN: string;
  167. begin
  168. FN := FileName + #0;
  169. {$ENDIF}
  170. asm
  171. mov ax, 4300h
  172. {$IFOPT H+}
  173. mov edx, FileName
  174. {$ELSE}
  175. lea edx, FN
  176. inc edx
  177. {$ENDIF}
  178. call syscall
  179. mov eax, 0
  180. jc @FExistsEnd
  181. test cx, 18h
  182. jnz @FExistsEnd
  183. inc eax
  184. @FExistsEnd:
  185. {$IFOPT H-}
  186. end;
  187. {$ENDIF}
  188. end;
  189. type TRec = record
  190. T, D: word;
  191. end;
  192. PSearchRec = ^SearchRec;
  193. function FindFirst (const Path: string; Attr: longint; var Rslt: TSearchRec): longint;
  194. var SR: PSearchRec;
  195. FStat: PFileFindBuf3;
  196. Count: longint;
  197. Err: longint;
  198. begin
  199. if os_mode = osOS2 then
  200. begin
  201. New (FStat);
  202. Rslt.FindHandle := $FFFFFFFF;
  203. Count := 1;
  204. Err := DosFindFirst (Path, Rslt.FindHandle, Attr, FStat,
  205. SizeOf (FStat^), Count, ilStandard);
  206. if (Err = 0) and (Count = 0) then Err := 18;
  207. FindFirst := -Err;
  208. if Err = 0 then
  209. begin
  210. Rslt.Name := FStat^.Name;
  211. Rslt.Size := FStat^.FileSize;
  212. Rslt.Attr := FStat^.AttrFile;
  213. Rslt.ExcludeAttr := 0;
  214. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  215. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  216. end;
  217. Dispose (FStat);
  218. end
  219. else
  220. begin
  221. GetMem (SR, SizeOf (SearchRec));
  222. Rslt.FindHandle := longint(SR);
  223. DOS.FindFirst (Path, Attr, SR^);
  224. FindFirst := -DosError;
  225. if DosError = 0 then
  226. begin
  227. Rslt.Time := SR^.Time;
  228. Rslt.Size := SR^.Size;
  229. Rslt.Attr := SR^.Attr;
  230. Rslt.ExcludeAttr := 0;
  231. Rslt.Name := SR^.Name;
  232. end;
  233. end;
  234. end;
  235. function FindNext (var Rslt: TSearchRec): longint;
  236. var SR: PSearchRec;
  237. FStat: PFileFindBuf3;
  238. Count: longint;
  239. Err: longint;
  240. begin
  241. if os_mode = osOS2 then
  242. begin
  243. New (FStat);
  244. Count := 1;
  245. Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat), Count);
  246. if (Err = 0) and (Count = 0) then Err := 18;
  247. FindNext := -Err;
  248. if Err = 0 then
  249. begin
  250. Rslt.Name := FStat^.Name;
  251. Rslt.Size := FStat^.FileSize;
  252. Rslt.Attr := FStat^.AttrFile;
  253. Rslt.ExcludeAttr := 0;
  254. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  255. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  256. end;
  257. Dispose (FStat);
  258. end
  259. else
  260. begin
  261. SR := PSearchRec (Rslt.FindHandle);
  262. if SR <> nil then
  263. begin
  264. DOS.FindNext (SR^);
  265. FindNext := -DosError;
  266. if DosError = 0 then
  267. begin
  268. Rslt.Time := SR^.Time;
  269. Rslt.Size := SR^.Size;
  270. Rslt.Attr := SR^.Attr;
  271. Rslt.ExcludeAttr := 0;
  272. Rslt.Name := SR^.Name;
  273. end;
  274. end;
  275. end;
  276. end;
  277. procedure FindClose (var F: TSearchrec);
  278. var SR: PSearchRec;
  279. begin
  280. if os_mode = osOS2 then
  281. begin
  282. DosFindClose (F.FindHandle);
  283. end
  284. else
  285. begin
  286. SR := PSearchRec (F.FindHandle);
  287. DOS.FindClose (SR^);
  288. FreeMem (SR, SizeOf (SearchRec));
  289. end;
  290. F.FindHandle := 0;
  291. end;
  292. function FileGetDate (Handle: longint): longint; assembler;
  293. asm
  294. mov ax, 5700h
  295. mov ebx, Handle
  296. call syscall
  297. mov eax, -1
  298. jc @FGetDateEnd
  299. mov ax, dx
  300. shld eax, ecx, 16
  301. @FGetDateEnd:
  302. end;
  303. function FileSetDate (Handle, Age: longint): longint;
  304. var FStat: PFileStatus0;
  305. RC: longint;
  306. begin
  307. if os_mode = osOS2 then
  308. begin
  309. New (FStat);
  310. RC := DosQueryFileInfo (Handle, ilStandard, FStat,
  311. SizeOf (FStat^));
  312. if RC <> 0 then
  313. FileSetDate := -1
  314. else
  315. begin
  316. FStat^.DateLastAccess := Hi (Age);
  317. FStat^.DateLastWrite := Hi (Age);
  318. FStat^.TimeLastAccess := Lo (Age);
  319. FStat^.TimeLastWrite := Lo (Age);
  320. RC := DosSetFileInfo (Handle, ilStandard, FStat,
  321. SizeOf (FStat^));
  322. if RC <> 0 then
  323. FileSetDate := -1
  324. else
  325. FileSetDate := 0;
  326. end;
  327. Dispose (FStat);
  328. end
  329. else
  330. asm
  331. mov ax, 5701h
  332. mov ebx, Handle
  333. mov cx, word ptr [Age]
  334. mov dx, word ptr [Age + 2]
  335. call syscall
  336. jnc @FSetDateEnd
  337. mov eax, -1
  338. @FSetDateEnd:
  339. mov [ebp - 4], eax
  340. end;
  341. end;
  342. function FileGetAttr (const FileName: string): longint;
  343. {$IFOPT H+}
  344. assembler;
  345. {$ELSE}
  346. var FN: string;
  347. begin
  348. FN := FileName + #0;
  349. {$ENDIF}
  350. asm
  351. mov ax, 4300h
  352. {$IFOPT H+}
  353. mov edx, FileName
  354. {$ELSE}
  355. lea edx, FN
  356. inc edx
  357. {$ENDIF}
  358. call syscall
  359. jnc @FGetAttrEnd
  360. mov eax, -1
  361. @FGetAttrEnd:
  362. {$IFOPT H-}
  363. mov [ebp - 4], eax
  364. end;
  365. {$ENDIF}
  366. end;
  367. function FileSetAttr (const Filename: string; Attr: longint): longint;
  368. {$IFOPT H+}
  369. assembler;
  370. {$ELSE}
  371. var FN: string;
  372. begin
  373. FN := FileName + #0;
  374. {$ENDIF}
  375. asm
  376. mov ax, 4301h
  377. mov ecx, Attr
  378. {$IFOPT H+}
  379. mov edx, FileName
  380. {$ELSE}
  381. lea edx, FN
  382. inc edx
  383. {$ENDIF}
  384. call syscall
  385. mov eax, 0
  386. jnc @FSetAttrEnd
  387. mov eax, -1
  388. @FSetAttrEnd:
  389. {$IFOPT H-}
  390. mov [ebp - 4], eax
  391. end;
  392. {$ENDIF}
  393. end;
  394. function DeleteFile (const FileName: string): boolean;
  395. {$IFOPT H+}
  396. assembler;
  397. {$ELSE}
  398. var FN: string;
  399. begin
  400. FN := FileName + #0;
  401. {$ENDIF}
  402. asm
  403. mov ax, 4100h
  404. {$IFOPT H+}
  405. mov edx, FileName
  406. {$ELSE}
  407. lea edx, FN
  408. inc edx
  409. {$ENDIF}
  410. call syscall
  411. mov eax, 0
  412. jc @FDeleteEnd
  413. inc eax
  414. @FDeleteEnd:
  415. {$IFOPT H-}
  416. mov [ebp - 4], eax
  417. end;
  418. {$ENDIF}
  419. end;
  420. function RenameFile (const OldName, NewName: string): boolean;
  421. {$IFOPT H+}
  422. assembler;
  423. {$ELSE}
  424. var FN1, FN2: string;
  425. begin
  426. FN1 := OldName + #0;
  427. FN2 := NewName + #0;
  428. {$ENDIF}
  429. asm
  430. mov ax, 5600h
  431. {$IFOPT H+}
  432. mov edx, OldName
  433. mov edi, NewName
  434. {$ELSE}
  435. lea edx, FN1
  436. inc edx
  437. lea edi, FN2
  438. inc edi
  439. {$ENDIF}
  440. call syscall
  441. mov eax, 0
  442. jc @FRenameEnd
  443. inc eax
  444. @FRenameEnd:
  445. {$IFOPT H-}
  446. mov [ebp - 4], eax
  447. end;
  448. {$ENDIF}
  449. end;
  450. function FileSearch (const Name, DirList: string): string;
  451. begin
  452. Result := Dos.FSearch (Name, DirList);
  453. end;
  454. {****************************************************************************
  455. Disk Functions
  456. ****************************************************************************}
  457. {$ASMMODE ATT}
  458. function DiskFree (Drive: byte): int64;
  459. var FI: TFSinfo;
  460. RC: longint;
  461. begin
  462. if (os_mode = osDOS) or (os_mode = osDPMI) then
  463. {Function 36 is not supported in OS/2.}
  464. asm
  465. movb 8(%ebp),%dl
  466. movb $0x36,%ah
  467. call syscall
  468. cmpw $-1,%ax
  469. je .LDISKFREE1
  470. mulw %cx
  471. mulw %bx
  472. shll $16,%edx
  473. movw %ax,%dx
  474. xchgl %edx,%eax
  475. leave
  476. ret
  477. .LDISKFREE1:
  478. cltd
  479. leave
  480. ret
  481. end
  482. else
  483. {In OS/2, we use the filesystem information.}
  484. begin
  485. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  486. if RC = 0 then
  487. DiskFree := int64 (FI.Free_Clusters) *
  488. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  489. else
  490. DiskFree := -1;
  491. end;
  492. end;
  493. function DiskSize (Drive: byte): int64;
  494. var FI: TFSinfo;
  495. RC: longint;
  496. begin
  497. if (os_mode = osDOS) or (os_mode = osDPMI) then
  498. {Function 36 is not supported in OS/2.}
  499. asm
  500. movb 8(%ebp),%dl
  501. movb $0x36,%ah
  502. call syscall
  503. movw %dx,%bx
  504. cmpw $-1,%ax
  505. je .LDISKSIZE1
  506. mulw %cx
  507. mulw %bx
  508. shll $16,%edx
  509. movw %ax,%dx
  510. xchgl %edx,%eax
  511. leave
  512. ret
  513. .LDISKSIZE1:
  514. cltd
  515. leave
  516. ret
  517. end
  518. else
  519. {In OS/2, we use the filesystem information.}
  520. begin
  521. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  522. if RC = 0 then
  523. DiskSize := int64 (FI.Total_Clusters) *
  524. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  525. else
  526. DiskSize := -1;
  527. end;
  528. end;
  529. function GetCurrentDir: string;
  530. begin
  531. GetDir (0, Result);
  532. end;
  533. function SetCurrentDir (const NewDir: string): boolean;
  534. begin
  535. {$I-}
  536. ChDir (NewDir);
  537. Result := (IOResult = 0);
  538. {$I+}
  539. end;
  540. function CreateDir (const NewDir: string): boolean;
  541. begin
  542. {$I-}
  543. MkDir (NewDir);
  544. Result := (IOResult = 0);
  545. {$I+}
  546. end;
  547. function RemoveDir (const Dir: string): boolean;
  548. begin
  549. {$I-}
  550. RmDir (Dir);
  551. Result := (IOResult = 0);
  552. {$I+}
  553. end;
  554. {****************************************************************************
  555. Time Functions
  556. ****************************************************************************}
  557. {$asmmode intel}
  558. procedure GetLocalTime (var SystemTime: TSystemTime); assembler;
  559. asm
  560. (* Expects the default record alignment (DWord)!!! *)
  561. mov ah, 2Ah
  562. call syscall
  563. mov edi, SystemTime
  564. xor eax, eax
  565. mov ax, cx
  566. stosd
  567. xor eax, eax
  568. mov al, dh
  569. stosd
  570. mov al, dl
  571. stosd
  572. push edi
  573. mov ah, 2Ch
  574. call syscall
  575. pop edi
  576. xor eax, eax
  577. mov al, ch
  578. stosd
  579. mov al, cl
  580. stosd
  581. mov al, dh
  582. stosd
  583. mov al, dl
  584. stosd
  585. end;
  586. {$asmmode default}
  587. {****************************************************************************
  588. Misc Functions
  589. ****************************************************************************}
  590. procedure Beep;
  591. begin
  592. end;
  593. {****************************************************************************
  594. Locale Functions
  595. ****************************************************************************}
  596. procedure InitAnsi;
  597. var I: byte;
  598. Country: TCountryCode;
  599. begin
  600. for I := 0 to 255 do
  601. UpperCaseTable [I] := Chr (I);
  602. Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
  603. if os_mode = osOS2 then
  604. begin
  605. FillChar (Country, SizeOf (Country), 0);
  606. DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
  607. end
  608. else
  609. begin
  610. (* !!! TODO: DOS/DPMI mode support!!! *)
  611. end;
  612. for I := 0 to 255 do
  613. if UpperCaseTable [I] <> Chr (I) then
  614. LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
  615. end;
  616. procedure InitInternational;
  617. var Country: TCountryCode;
  618. CtryInfo: TCountryInfo;
  619. Size: cardinal;
  620. RC: longint;
  621. begin
  622. Size := 0;
  623. FillChar (Country, SizeOf (Country), 0);
  624. FillChar (CtryInfo, SizeOf (CtryInfo), 0);
  625. RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
  626. if RC = 0 then
  627. begin
  628. DateSeparator := CtryInfo.DateSeparator;
  629. case CtryInfo.DateFormat of
  630. 1: begin
  631. ShortDateFormat := 'd/m/y';
  632. LongDateFormat := 'dd" "mmmm" "yyyy';
  633. end;
  634. 2: begin
  635. ShortDateFormat := 'y/m/d';
  636. LongDateFormat := 'yyyy" "mmmm" "dd';
  637. end;
  638. 3: begin
  639. ShortDateFormat := 'm/d/y';
  640. LongDateFormat := 'mmmm" "dd" "yyyy';
  641. end;
  642. end;
  643. TimeSeparator := CtryInfo.TimeSeparator;
  644. DecimalSeparator := CtryInfo.DecimalSeparator;
  645. ThousandSeparator := CtryInfo.ThousandSeparator;
  646. CurrencyFormat := CtryInfo.CurrencyFormat;
  647. CurrencyString := PChar (CtryInfo.CurrencyUnit);
  648. end;
  649. InitAnsi;
  650. end;
  651. function SysErrorMessage(ErrorCode: Integer): String;
  652. begin
  653. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  654. end;
  655. {****************************************************************************
  656. Initialization code
  657. ****************************************************************************}
  658. Initialization
  659. InitExceptions; { Initialize exceptions. OS independent }
  660. InitInternational; { Initialize internationalization settings }
  661. Finalization
  662. OutOfMemory.Free;
  663. InValidPointer.Free;
  664. end.
  665. {
  666. $Log$
  667. Revision 1.6 2000-10-15 20:44:18 hajny
  668. * FindClose correction
  669. Revision 1.5 2000/09/29 21:49:41 jonas
  670. * removed warnings
  671. Revision 1.4 2000/08/30 06:30:55 michael
  672. + Merged syserrormsg fix
  673. Revision 1.3 2000/08/25 17:23:56 hajny
  674. * Sharing mode error fixed
  675. Revision 1.2 2000/08/20 15:46:46 peter
  676. * sysutils.pp moved to target and merged with disk.inc, filutil.inc
  677. Revision 1.1.2.3 2000/08/25 17:20:57 hajny
  678. * Sharing mode error fixed
  679. Revision 1.1.2.2 2000/08/22 19:21:48 michael
  680. + Implemented syserrormessage. Made dummies for go32v2 and OS/2
  681. * Changed linux/errors.pp so it uses pchars for storage.
  682. Revision 1.1.2.1 2000/08/20 15:08:32 peter
  683. * forgot the add command :(
  684. }