sysutils.pp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  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. DOS.FindClose (SR^);
  287. FreeMem (SR, SizeOf (SearchRec));
  288. end};
  289. F.FindHandle := 0;
  290. end;
  291. function FileGetDate (Handle: longint): longint; assembler;
  292. asm
  293. mov ax, 5700h
  294. mov ebx, Handle
  295. call syscall
  296. mov eax, -1
  297. jc @FGetDateEnd
  298. mov ax, dx
  299. shld eax, ecx, 16
  300. @FGetDateEnd:
  301. end;
  302. function FileSetDate (Handle, Age: longint): longint;
  303. var FStat: PFileStatus0;
  304. RC: longint;
  305. begin
  306. if os_mode = osOS2 then
  307. begin
  308. New (FStat);
  309. RC := DosQueryFileInfo (Handle, ilStandard, FStat,
  310. SizeOf (FStat^));
  311. if RC <> 0 then
  312. FileSetDate := -1
  313. else
  314. begin
  315. FStat^.DateLastAccess := Hi (Age);
  316. FStat^.DateLastWrite := Hi (Age);
  317. FStat^.TimeLastAccess := Lo (Age);
  318. FStat^.TimeLastWrite := Lo (Age);
  319. RC := DosSetFileInfo (Handle, ilStandard, FStat,
  320. SizeOf (FStat^));
  321. if RC <> 0 then
  322. FileSetDate := -1
  323. else
  324. FileSetDate := 0;
  325. end;
  326. Dispose (FStat);
  327. end
  328. else
  329. asm
  330. mov ax, 5701h
  331. mov ebx, Handle
  332. mov cx, word ptr [Age]
  333. mov dx, word ptr [Age + 2]
  334. call syscall
  335. jnc @FSetDateEnd
  336. mov eax, -1
  337. @FSetDateEnd:
  338. mov [ebp - 4], eax
  339. end;
  340. end;
  341. function FileGetAttr (const FileName: string): longint;
  342. {$IFOPT H+}
  343. assembler;
  344. {$ELSE}
  345. var FN: string;
  346. begin
  347. FN := FileName + #0;
  348. {$ENDIF}
  349. asm
  350. mov ax, 4300h
  351. {$IFOPT H+}
  352. mov edx, FileName
  353. {$ELSE}
  354. lea edx, FN
  355. inc edx
  356. {$ENDIF}
  357. call syscall
  358. jnc @FGetAttrEnd
  359. mov eax, -1
  360. @FGetAttrEnd:
  361. {$IFOPT H-}
  362. mov [ebp - 4], eax
  363. end;
  364. {$ENDIF}
  365. end;
  366. function FileSetAttr (const Filename: string; Attr: longint): longint;
  367. {$IFOPT H+}
  368. assembler;
  369. {$ELSE}
  370. var FN: string;
  371. begin
  372. FN := FileName + #0;
  373. {$ENDIF}
  374. asm
  375. mov ax, 4301h
  376. mov ecx, Attr
  377. {$IFOPT H+}
  378. mov edx, FileName
  379. {$ELSE}
  380. lea edx, FN
  381. inc edx
  382. {$ENDIF}
  383. call syscall
  384. mov eax, 0
  385. jnc @FSetAttrEnd
  386. mov eax, -1
  387. @FSetAttrEnd:
  388. {$IFOPT H-}
  389. mov [ebp - 4], eax
  390. end;
  391. {$ENDIF}
  392. end;
  393. function DeleteFile (const FileName: string): boolean;
  394. {$IFOPT H+}
  395. assembler;
  396. {$ELSE}
  397. var FN: string;
  398. begin
  399. FN := FileName + #0;
  400. {$ENDIF}
  401. asm
  402. mov ax, 4100h
  403. {$IFOPT H+}
  404. mov edx, FileName
  405. {$ELSE}
  406. lea edx, FN
  407. inc edx
  408. {$ENDIF}
  409. call syscall
  410. mov eax, 0
  411. jc @FDeleteEnd
  412. inc eax
  413. @FDeleteEnd:
  414. {$IFOPT H-}
  415. mov [ebp - 4], eax
  416. end;
  417. {$ENDIF}
  418. end;
  419. function RenameFile (const OldName, NewName: string): boolean;
  420. {$IFOPT H+}
  421. assembler;
  422. {$ELSE}
  423. var FN1, FN2: string;
  424. begin
  425. FN1 := OldName + #0;
  426. FN2 := NewName + #0;
  427. {$ENDIF}
  428. asm
  429. mov ax, 5600h
  430. {$IFOPT H+}
  431. mov edx, OldName
  432. mov edi, NewName
  433. {$ELSE}
  434. lea edx, FN1
  435. inc edx
  436. lea edi, FN2
  437. inc edi
  438. {$ENDIF}
  439. call syscall
  440. mov eax, 0
  441. jc @FRenameEnd
  442. inc eax
  443. @FRenameEnd:
  444. {$IFOPT H-}
  445. mov [ebp - 4], eax
  446. end;
  447. {$ENDIF}
  448. end;
  449. function FileSearch (const Name, DirList: string): string;
  450. begin
  451. Result := Dos.FSearch (Name, DirList);
  452. end;
  453. {****************************************************************************
  454. Disk Functions
  455. ****************************************************************************}
  456. {$ASMMODE ATT}
  457. function DiskFree (Drive: byte): int64;
  458. var FI: TFSinfo;
  459. RC: longint;
  460. begin
  461. if (os_mode = osDOS) or (os_mode = osDPMI) then
  462. {Function 36 is not supported in OS/2.}
  463. asm
  464. movb 8(%ebp),%dl
  465. movb $0x36,%ah
  466. call syscall
  467. cmpw $-1,%ax
  468. je .LDISKFREE1
  469. mulw %cx
  470. mulw %bx
  471. shll $16,%edx
  472. movw %ax,%dx
  473. xchgl %edx,%eax
  474. leave
  475. ret
  476. .LDISKFREE1:
  477. cltd
  478. leave
  479. ret
  480. end
  481. else
  482. {In OS/2, we use the filesystem information.}
  483. begin
  484. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  485. if RC = 0 then
  486. DiskFree := int64 (FI.Free_Clusters) *
  487. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  488. else
  489. DiskFree := -1;
  490. end;
  491. end;
  492. function DiskSize (Drive: byte): int64;
  493. var FI: TFSinfo;
  494. RC: longint;
  495. begin
  496. if (os_mode = osDOS) or (os_mode = osDPMI) then
  497. {Function 36 is not supported in OS/2.}
  498. asm
  499. movb 8(%ebp),%dl
  500. movb $0x36,%ah
  501. call syscall
  502. movw %dx,%bx
  503. cmpw $-1,%ax
  504. je .LDISKSIZE1
  505. mulw %cx
  506. mulw %bx
  507. shll $16,%edx
  508. movw %ax,%dx
  509. xchgl %edx,%eax
  510. leave
  511. ret
  512. .LDISKSIZE1:
  513. cltd
  514. leave
  515. ret
  516. end
  517. else
  518. {In OS/2, we use the filesystem information.}
  519. begin
  520. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  521. if RC = 0 then
  522. DiskSize := int64 (FI.Total_Clusters) *
  523. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  524. else
  525. DiskSize := -1;
  526. end;
  527. end;
  528. function GetCurrentDir: string;
  529. begin
  530. GetDir (0, Result);
  531. end;
  532. function SetCurrentDir (const NewDir: string): boolean;
  533. begin
  534. {$I-}
  535. ChDir (NewDir);
  536. Result := (IOResult = 0);
  537. {$I+}
  538. end;
  539. function CreateDir (const NewDir: string): boolean;
  540. begin
  541. {$I-}
  542. MkDir (NewDir);
  543. Result := (IOResult = 0);
  544. {$I+}
  545. end;
  546. function RemoveDir (const Dir: string): boolean;
  547. begin
  548. {$I-}
  549. RmDir (Dir);
  550. Result := (IOResult = 0);
  551. {$I+}
  552. end;
  553. {****************************************************************************
  554. Time Functions
  555. ****************************************************************************}
  556. {$asmmode intel}
  557. procedure GetLocalTime (var SystemTime: TSystemTime); assembler;
  558. asm
  559. (* Expects the default record alignment (DWord)!!! *)
  560. mov ah, 2Ah
  561. call syscall
  562. mov edi, SystemTime
  563. xor eax, eax
  564. mov ax, cx
  565. stosd
  566. xor eax, eax
  567. mov al, dh
  568. stosd
  569. mov al, dl
  570. stosd
  571. push edi
  572. mov ah, 2Ch
  573. call syscall
  574. pop edi
  575. xor eax, eax
  576. mov al, ch
  577. stosd
  578. mov al, cl
  579. stosd
  580. mov al, dh
  581. stosd
  582. mov al, dl
  583. stosd
  584. end;
  585. {$asmmode default}
  586. {****************************************************************************
  587. Misc Functions
  588. ****************************************************************************}
  589. procedure Beep;
  590. begin
  591. end;
  592. {****************************************************************************
  593. Locale Functions
  594. ****************************************************************************}
  595. procedure InitAnsi;
  596. var I: byte;
  597. Country: TCountryCode;
  598. begin
  599. for I := 0 to 255 do
  600. UpperCaseTable [I] := Chr (I);
  601. Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
  602. if os_mode = osOS2 then
  603. begin
  604. FillChar (Country, SizeOf (Country), 0);
  605. DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
  606. end
  607. else
  608. begin
  609. (* !!! TODO: DOS/DPMI mode support!!! *)
  610. end;
  611. for I := 0 to 255 do
  612. if UpperCaseTable [I] <> Chr (I) then
  613. LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
  614. end;
  615. procedure InitInternational;
  616. var Country: TCountryCode;
  617. CtryInfo: TCountryInfo;
  618. Size: cardinal;
  619. RC: longint;
  620. begin
  621. Size := 0;
  622. FillChar (Country, SizeOf (Country), 0);
  623. FillChar (CtryInfo, SizeOf (CtryInfo), 0);
  624. RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
  625. if RC = 0 then
  626. begin
  627. DateSeparator := CtryInfo.DateSeparator;
  628. case CtryInfo.DateFormat of
  629. 1: begin
  630. ShortDateFormat := 'd/m/y';
  631. LongDateFormat := 'dd" "mmmm" "yyyy';
  632. end;
  633. 2: begin
  634. ShortDateFormat := 'y/m/d';
  635. LongDateFormat := 'yyyy" "mmmm" "dd';
  636. end;
  637. 3: begin
  638. ShortDateFormat := 'm/d/y';
  639. LongDateFormat := 'mmmm" "dd" "yyyy';
  640. end;
  641. end;
  642. TimeSeparator := CtryInfo.TimeSeparator;
  643. DecimalSeparator := CtryInfo.DecimalSeparator;
  644. ThousandSeparator := CtryInfo.ThousandSeparator;
  645. CurrencyFormat := CtryInfo.CurrencyFormat;
  646. CurrencyString := PChar (CtryInfo.CurrencyUnit);
  647. end;
  648. InitAnsi;
  649. end;
  650. function SysErrorMessage(ErrorCode: Integer): String;
  651. begin
  652. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  653. end;
  654. {****************************************************************************
  655. Initialization code
  656. ****************************************************************************}
  657. Initialization
  658. InitExceptions; { Initialize exceptions. OS independent }
  659. InitInternational; { Initialize internationalization settings }
  660. Finalization
  661. OutOfMemory.Free;
  662. InValidPointer.Free;
  663. end.
  664. {
  665. $Log$
  666. Revision 1.5 2000-09-29 21:49:41 jonas
  667. * removed warnings
  668. Revision 1.4 2000/08/30 06:30:55 michael
  669. + Merged syserrormsg fix
  670. Revision 1.3 2000/08/25 17:23:56 hajny
  671. * Sharing mode error fixed
  672. Revision 1.2 2000/08/20 15:46:46 peter
  673. * sysutils.pp moved to target and merged with disk.inc, filutil.inc
  674. Revision 1.1.2.3 2000/08/25 17:20:57 hajny
  675. * Sharing mode error fixed
  676. Revision 1.1.2.2 2000/08/22 19:21:48 michael
  677. + Implemented syserrormessage. Made dummies for go32v2 and OS/2
  678. * Changed linux/errors.pp so it uses pchars for storage.
  679. Revision 1.1.2.1 2000/08/20 15:08:32 peter
  680. * forgot the add command :(
  681. }