sysutils.pp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Sysutils unit for Watcom
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$inline on}
  13. unit sysutils;
  14. interface
  15. {$MODE objfpc}
  16. {$modeswitch out}
  17. { force ansistrings }
  18. {$H+}
  19. uses
  20. watcom,dos;
  21. {$DEFINE HAS_SLEEP}
  22. { Include platform independent interface part }
  23. {$i sysutilh.inc}
  24. implementation
  25. uses
  26. sysconst;
  27. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  28. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  29. { used OS file system APIs use ansistring }
  30. {$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
  31. { Include platform independent implementation part }
  32. {$i sysutils.inc}
  33. {****************************************************************************
  34. File Functions
  35. ****************************************************************************}
  36. { some internal constants }
  37. const
  38. ofRead = $0000; { Open for reading }
  39. ofWrite = $0001; { Open for writing }
  40. ofReadWrite = $0002; { Open for reading/writing }
  41. faFail = $0000; { Fail if file does not exist }
  42. faCreate = $0010; { Create if file does not exist }
  43. faOpen = $0001; { Open if file exists }
  44. faOpenReplace = $0002; { Clear if file exists }
  45. Type
  46. PSearchrec = ^Searchrec;
  47. { converts S to a pchar and copies it to the transfer-buffer. }
  48. procedure StringToTB(const S: RawByteString);
  49. begin
  50. { include terminating null char }
  51. SysCopyToDos(longint(pointer(s)), Length(S) + 1);
  52. end ;
  53. { Native OpenFile function.
  54. if return value <> 0 call failed. }
  55. function OpenFile(const FileName: RawByteString; var Handle: longint; Mode, Action: word): longint;
  56. var
  57. Regs: registers;
  58. SystemFileName: RawByteString;
  59. begin
  60. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  61. result := 0;
  62. Handle := 0;
  63. StringToTB(SystemFileName);
  64. if LFNSupport then
  65. Regs.Eax := $716c { Use LFN Open/Create API }
  66. else { Check if Extended Open/Create API is safe to use }
  67. if lo(dosversion) < 7 then
  68. Regs.Eax := $3d00 + (Mode and $ff) { For now, map to Open API }
  69. else
  70. Regs.Eax := $6c00; { Use Extended Open/Create API }
  71. if Regs.Ah = $3d then
  72. begin
  73. if (Action and $00f0) <> 0 then
  74. Regs.Eax := $3c00; { Map to Create/Replace API }
  75. Regs.Ds := tb_segment;
  76. Regs.Edx := tb_offset;
  77. end
  78. else { LFN or Extended Open/Create API }
  79. begin
  80. Regs.Edx := Action; { Action if file exists/not exists }
  81. Regs.Ds := tb_segment;
  82. Regs.Esi := tb_offset;
  83. Regs.Ebx := $2000 + (Mode and $ff); { file open mode }
  84. end;
  85. Regs.Ecx := $20; { Attributes }
  86. RealIntr($21, Regs);
  87. if (Regs.Flags and CarryFlag) <> 0 then
  88. result := Regs.Ax
  89. else
  90. Handle := Regs.Ax;
  91. end;
  92. Function FileOpen (Const FileName : rawbytestring; Mode : Integer) : Longint;
  93. Var
  94. e: integer;
  95. Begin
  96. e := OpenFile(FileName, result, Mode, faOpen);
  97. if e <> 0 then
  98. result := -1;
  99. end;
  100. Function FileCreate (Const FileName : RawByteString) : Longint;
  101. var
  102. e: integer;
  103. begin
  104. e := OpenFile(FileName, result, ofReadWrite, faCreate or faOpenReplace);
  105. if e <> 0 then
  106. result := -1;
  107. end;
  108. Function FileCreate (Const FileName : RawByteString; Rights:longint) : Longint;
  109. begin
  110. FileCreate:=FileCreate(FileName);
  111. end;
  112. Function FileCreate (Const FileName : RawByteString; ShareMode:longint; Rights: Longint) : Longint;
  113. begin
  114. FileCreate:=FileCreate(FileName);
  115. end;
  116. Function FileRead (Handle : Longint; Out Buffer; Count : longint) : Longint;
  117. var
  118. regs : registers;
  119. size,
  120. readsize : longint;
  121. begin
  122. readsize:=0;
  123. while Count > 0 do
  124. begin
  125. if Count>tb_size then
  126. size:=tb_size
  127. else
  128. size:=Count;
  129. regs.realecx:=size;
  130. regs.realedx:=tb_offset;
  131. regs.realds:=tb_segment;
  132. regs.realebx:=Handle;
  133. regs.realeax:=$3f00;
  134. RealIntr($21,regs);
  135. if (regs.realflags and carryflag) <> 0 then
  136. begin
  137. Result:=-1;
  138. exit;
  139. end;
  140. syscopyfromdos(Longint(@Buffer)+readsize,lo(regs.realeax));
  141. inc(readsize,lo(regs.realeax));
  142. dec(Count,lo(regs.realeax));
  143. { stop when not the specified size is read }
  144. if lo(regs.realeax)<size then
  145. break;
  146. end;
  147. Result:=readsize;
  148. end;
  149. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  150. var
  151. regs : registers;
  152. size,
  153. writesize : longint;
  154. begin
  155. writesize:=0;
  156. while Count > 0 do
  157. begin
  158. if Count>tb_size then
  159. size:=tb_size
  160. else
  161. size:=Count;
  162. syscopytodos(Longint(@Buffer)+writesize,size);
  163. regs.realecx:=size;
  164. regs.realedx:=tb_offset;
  165. regs.realds:=tb_segment;
  166. regs.realebx:=Handle;
  167. regs.realeax:=$4000;
  168. RealIntr($21,regs);
  169. if (regs.realflags and carryflag) <> 0 then
  170. begin
  171. Result:=-1;
  172. exit;
  173. end;
  174. inc(writesize,lo(regs.realeax));
  175. dec(Count,lo(regs.realeax));
  176. { stop when not the specified size is written }
  177. if lo(regs.realeax)<size then
  178. break;
  179. end;
  180. Result:=WriteSize;
  181. end;
  182. Function FileSeek (Handle, FOffset, Origin : Longint) : Longint;
  183. var
  184. Regs: registers;
  185. begin
  186. Regs.Eax := $4200;
  187. Regs.Al := Origin;
  188. Regs.Edx := Lo(FOffset);
  189. Regs.Ecx := Hi(FOffset);
  190. Regs.Ebx := Handle;
  191. RealIntr($21, Regs);
  192. if Regs.Flags and CarryFlag <> 0 then
  193. result := -1
  194. else begin
  195. LongRec(result).Lo := Regs.Ax;
  196. LongRec(result).Hi := Regs.Dx;
  197. end ;
  198. end;
  199. Function FileSeek (Handle : Longint; FOffset: Int64; Origin: Longint) : Int64;
  200. begin
  201. {$warning need to add 64bit call }
  202. FileSeek:=FileSeek(Handle,Longint(FOffset),Longint(Origin));
  203. end;
  204. Procedure FileClose (Handle : Longint);
  205. var
  206. Regs: registers;
  207. begin
  208. if Handle<=4 then
  209. exit;
  210. Regs.Eax := $3e00;
  211. Regs.Ebx := Handle;
  212. RealIntr($21, Regs);
  213. end;
  214. Function FileTruncate (Handle: THandle; Size: Int64) : boolean;
  215. var
  216. regs : trealregs;
  217. begin
  218. if Size > high (longint) then
  219. FileTruncate := false
  220. else
  221. begin
  222. FileSeek(Handle,Size,0);
  223. Regs.realecx := 0;
  224. Regs.realedx := tb_offset;
  225. Regs.ds := tb_segment;
  226. Regs.ebx := Handle;
  227. Regs.eax:=$4000;
  228. RealIntr($21, Regs);
  229. FileTruncate:=(regs.realflags and carryflag)=0;
  230. end;
  231. end;
  232. Function FileAge (Const FileName : String): Longint;
  233. var Handle: longint;
  234. begin
  235. Handle := FileOpen(FileName, 0);
  236. if Handle <> -1 then
  237. begin
  238. result := FileGetDate(Handle);
  239. FileClose(Handle);
  240. end
  241. else
  242. result := -1;
  243. end;
  244. function FileExists (const FileName: RawByteString): boolean;
  245. var
  246. L: longint;
  247. begin
  248. { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }
  249. if FileName = '' then
  250. Result := false
  251. else
  252. begin
  253. L := FileGetAttr (FileName);
  254. Result := (L >= 0) and (L and (faDirectory or faVolumeID) = 0);
  255. (* Neither VolumeIDs nor directories are files. *)
  256. end;
  257. end;
  258. function DirectoryExists (const Directory: RawByteString): boolean;
  259. var
  260. L: longint;
  261. begin
  262. { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }
  263. if Directory = '' then
  264. Result := false
  265. else
  266. begin
  267. if ((Length (Directory) = 2) or
  268. (Length (Directory) = 3) and
  269. (Directory [3] in AllowDirectorySeparators)) and
  270. (Directory [2] in AllowDriveSeparators) and
  271. (UpCase (Directory [1]) in ['A'..'Z']) then
  272. (* Checking attributes for 'x:' is not possible but for 'x:.' it is. *)
  273. L := FileGetAttr (Directory + '.')
  274. else if (Directory [Length (Directory)] in AllowDirectorySeparators) and
  275. (Length (Directory) > 1) and
  276. (* Do not remove '\' in '\\' (invalid path, possibly broken UNC path). *)
  277. not (Directory [Length (Directory) - 1] in AllowDirectorySeparators) then
  278. L := FileGetAttr (Copy (Directory, 1, Length (Directory) - 1))
  279. else
  280. L := FileGetAttr (Directory);
  281. Result := (L > 0) and (L and faDirectory = faDirectory);
  282. end;
  283. end;
  284. Function FindFirst (Const Path : String; Attr : Longint; out Rslt : TSearchRec) : Longint;
  285. Var Sr : PSearchrec;
  286. begin
  287. //!! Sr := New(PSearchRec);
  288. getmem(sr,sizeof(searchrec));
  289. Rslt.FindHandle := longint(Sr);
  290. DOS.FindFirst(Path, Attr, Sr^);
  291. result := -DosError;
  292. if result = 0 then
  293. begin
  294. Rslt.Time := Sr^.Time;
  295. Rslt.Size := Sr^.Size;
  296. Rslt.Attr := Sr^.Attr;
  297. Rslt.ExcludeAttr := 0;
  298. Rslt.Name := Sr^.Name;
  299. end ;
  300. end;
  301. Function FindNext (Var Rslt : TSearchRec) : Longint;
  302. var
  303. Sr: PSearchRec;
  304. begin
  305. Sr := PSearchRec(Rslt.FindHandle);
  306. if Sr <> nil then
  307. begin
  308. DOS.FindNext(Sr^);
  309. result := -DosError;
  310. if result = 0 then
  311. begin
  312. Rslt.Time := Sr^.Time;
  313. Rslt.Size := Sr^.Size;
  314. Rslt.Attr := Sr^.Attr;
  315. Rslt.ExcludeAttr := 0;
  316. Rslt.Name := Sr^.Name;
  317. end;
  318. end;
  319. end;
  320. Procedure FindClose (Var F : TSearchrec);
  321. var
  322. Sr: PSearchRec;
  323. begin
  324. Sr := PSearchRec(F.FindHandle);
  325. if Sr <> nil then
  326. begin
  327. //!! Dispose(Sr);
  328. // This call is non dummy if LFNSupport is true PM
  329. DOS.FindClose(SR^);
  330. freemem(sr,sizeof(searchrec));
  331. end;
  332. F.FindHandle := 0;
  333. end;
  334. Function FileGetDate (Handle : Longint) : Longint;
  335. var
  336. Regs: registers;
  337. begin
  338. //!! for win95 an alternative function is available.
  339. Regs.Ebx := Handle;
  340. Regs.Eax := $5700;
  341. RealIntr($21, Regs);
  342. if Regs.Flags and CarryFlag <> 0 then
  343. result := -1
  344. else
  345. begin
  346. LongRec(result).Lo := Regs.cx;
  347. LongRec(result).Hi := Regs.dx;
  348. end ;
  349. end;
  350. Function FileSetDate (Handle, Age : Longint) : Longint;
  351. var
  352. Regs: registers;
  353. begin
  354. Regs.Ebx := Handle;
  355. Regs.Eax := $5701;
  356. Regs.Ecx := Lo(Age);
  357. Regs.Edx := Hi(Age);
  358. RealIntr($21, Regs);
  359. if Regs.Flags and CarryFlag <> 0 then
  360. result := -Regs.Ax
  361. else
  362. result := 0;
  363. end;
  364. Function FileGetAttr (Const FileName : RawByteString) : Longint;
  365. var
  366. Regs: registers;
  367. SystemFileName: RawByteString;
  368. begin
  369. SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
  370. StringToTB(SystemFileName);
  371. Regs.Edx := tb_offset;
  372. Regs.Ds := tb_segment;
  373. if LFNSupport then
  374. begin
  375. Regs.Ax := $7143;
  376. Regs.Bx := 0;
  377. end
  378. else
  379. Regs.Ax := $4300;
  380. RealIntr($21, Regs);
  381. if Regs.Flags and CarryFlag <> 0 then
  382. result := -1
  383. else
  384. result := Regs.Cx;
  385. end;
  386. Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
  387. var
  388. Regs: registers;
  389. SystemFileName: RawByteString;
  390. begin
  391. SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
  392. StringToTB(SystemFileName);
  393. Regs.Edx := tb_offset;
  394. Regs.Ds := tb_segment;
  395. if LFNSupport then
  396. begin
  397. Regs.Ax := $7143;
  398. Regs.Bx := 1;
  399. end
  400. else
  401. Regs.Ax := $4301;
  402. Regs.Cx := Attr;
  403. RealIntr($21, Regs);
  404. if Regs.Flags and CarryFlag <> 0 then
  405. result := -Regs.Ax
  406. else
  407. result := 0;
  408. end;
  409. Function DeleteFile (Const FileName : RawByteString) : Boolean;
  410. var
  411. Regs: registers;
  412. SystemFileName: RawByteString;
  413. begin
  414. SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
  415. StringToTB(SystemFileName);
  416. Regs.Edx := tb_offset;
  417. Regs.Ds := tb_segment;
  418. if LFNSupport then
  419. Regs.Eax := $7141
  420. else
  421. Regs.Eax := $4100;
  422. Regs.Esi := 0;
  423. Regs.Ecx := 0;
  424. RealIntr($21, Regs);
  425. result := (Regs.Flags and CarryFlag = 0);
  426. end;
  427. Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;
  428. var
  429. Regs: registers;
  430. OldSystemFileName, NewSystemFileName: RawByteString;
  431. begin
  432. OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName);
  433. NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewFile);
  434. StringToTB(OldSystemFileName + #0 + NewSystemFileName);
  435. Regs.Edx := tb_offset;
  436. Regs.Ds := tb_segment;
  437. Regs.Edi := tb_offset + Length(OldSystemFileName) + 1;
  438. Regs.Es := tb_segment;
  439. if LFNSupport then
  440. Regs.Eax := $7156
  441. else
  442. Regs.Eax := $5600;
  443. Regs.Ecx := $ff;
  444. RealIntr($21, Regs);
  445. result := (Regs.Flags and CarryFlag = 0);
  446. end;
  447. {****************************************************************************
  448. Disk Functions
  449. ****************************************************************************}
  450. TYPE ExtendedFat32FreeSpaceRec=packed Record
  451. RetSize : WORD; { (ret) size of returned structure}
  452. Strucversion : WORD; {(call) structure version (0000h)
  453. (ret) actual structure version (0000h)}
  454. SecPerClus, {number of sectors per cluster}
  455. BytePerSec, {number of bytes per sector}
  456. AvailClusters, {number of available clusters}
  457. TotalClusters, {total number of clusters on the drive}
  458. AvailPhysSect, {physical sectors available on the drive}
  459. TotalPhysSect, {total physical sectors on the drive}
  460. AvailAllocUnits, {Available allocation units}
  461. TotalAllocUnits : DWORD; {Total allocation units}
  462. Dummy,Dummy2 : DWORD; {8 bytes reserved}
  463. END;
  464. function do_diskdata(drive : byte; Free : BOOLEAN) : Int64;
  465. VAR S : String;
  466. Rec : ExtendedFat32FreeSpaceRec;
  467. regs : registers;
  468. procedure OldDosDiskData;
  469. begin
  470. regs.dl:=drive;
  471. regs.ah:=$36;
  472. msdos(regs);
  473. if regs.ax<>$FFFF then
  474. begin
  475. if Free then
  476. Do_DiskData:=int64(regs.ax)*regs.bx*regs.cx
  477. else
  478. Do_DiskData:=int64(regs.ax)*regs.cx*regs.dx;
  479. end
  480. else
  481. do_diskdata:=-1;
  482. end;
  483. BEGIN
  484. if LFNSupport then
  485. begin
  486. S:='C:\'#0;
  487. if Drive=0 then
  488. begin
  489. GetDir(Drive,S);
  490. Setlength(S,4);
  491. S[4]:=#0;
  492. end
  493. else
  494. S[1]:=chr(Drive+64);
  495. Rec.Strucversion:=0;
  496. Rec.RetSize := 0;
  497. dosmemput(tb_segment,tb_offset,Rec,SIZEOF(ExtendedFat32FreeSpaceRec));
  498. dosmemput(tb_segment,tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1,S[1],4);
  499. regs.dx:=tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1;
  500. regs.ds:=tb_segment;
  501. regs.di:=tb_offset;
  502. regs.es:=tb_segment;
  503. regs.cx:=Sizeof(ExtendedFat32FreeSpaceRec);
  504. regs.ax:=$7303;
  505. msdos(regs);
  506. if (regs.flags and fcarry) = 0 then {No error clausule in int except cf}
  507. begin
  508. copyfromdos(rec,Sizeof(ExtendedFat32FreeSpaceRec));
  509. if Rec.RetSize = 0 then (* Error - "FAT32" function not supported! *)
  510. OldDosDiskData
  511. else
  512. if Free then
  513. Do_DiskData:=int64(rec.AvailAllocUnits)*rec.SecPerClus*rec.BytePerSec
  514. else
  515. Do_DiskData:=int64(rec.TotalAllocUnits)*rec.SecPerClus*rec.BytePerSec;
  516. end
  517. else
  518. Do_DiskData:=-1;
  519. end
  520. else
  521. OldDosDiskData;
  522. end;
  523. function diskfree(drive : byte) : int64;
  524. begin
  525. diskfree:=Do_DiskData(drive,TRUE);
  526. end;
  527. function disksize(drive : byte) : int64;
  528. begin
  529. disksize:=Do_DiskData(drive,false);
  530. end;
  531. Function GetCurrentDir : String;
  532. begin
  533. GetDir(0, result);
  534. end;
  535. Function SetCurrentDir (Const NewDir : String) : Boolean;
  536. begin
  537. {$I-}
  538. ChDir(NewDir);
  539. {$I+}
  540. result := (IOResult = 0);
  541. end;
  542. Function CreateDir (Const NewDir : String) : Boolean;
  543. begin
  544. {$I-}
  545. MkDir(NewDir);
  546. {$I+}
  547. result := (IOResult = 0);
  548. end;
  549. Function RemoveDir (Const Dir : String) : Boolean;
  550. begin
  551. {$I-}
  552. RmDir(Dir);
  553. {$I+}
  554. result := (IOResult = 0);
  555. end;
  556. {****************************************************************************
  557. Time Functions
  558. ****************************************************************************}
  559. Procedure GetLocalTime(var SystemTime: TSystemTime);
  560. var
  561. Regs: Registers;
  562. begin
  563. Regs.ah := $2C;
  564. RealIntr($21, Regs);
  565. SystemTime.Hour := Regs.Ch;
  566. SystemTime.Minute := Regs.Cl;
  567. SystemTime.Second := Regs.Dh;
  568. SystemTime.MilliSecond := Regs.Dl*10;
  569. Regs.ah := $2A;
  570. RealIntr($21, Regs);
  571. SystemTime.Year := Regs.Cx;
  572. SystemTime.Month := Regs.Dh;
  573. SystemTime.Day := Regs.Dl;
  574. end ;
  575. {****************************************************************************
  576. Misc Functions
  577. ****************************************************************************}
  578. procedure Beep;
  579. begin
  580. end;
  581. {****************************************************************************
  582. Locale Functions
  583. ****************************************************************************}
  584. { Codepage constants }
  585. const
  586. CP_US = 437;
  587. CP_MultiLingual = 850;
  588. CP_SlavicLatin2 = 852;
  589. CP_Turkish = 857;
  590. CP_Portugal = 860;
  591. CP_IceLand = 861;
  592. CP_Canada = 863;
  593. CP_NorwayDenmark = 865;
  594. { CountryInfo }
  595. type
  596. TCountryInfo = packed record
  597. InfoId: byte;
  598. case integer of
  599. 1: ( Size: word;
  600. CountryId: word;
  601. CodePage: word;
  602. CountryInfo: array[0..33] of byte );
  603. 2: ( UpperCaseTable: longint );
  604. 4: ( FilenameUpperCaseTable: longint );
  605. 5: ( FilecharacterTable: longint );
  606. 6: ( CollatingTable: longint );
  607. 7: ( DBCSLeadByteTable: longint );
  608. end ;
  609. procedure GetExtendedCountryInfo(InfoId: integer; CodePage, CountryId: word; var CountryInfo: TCountryInfo);
  610. Var Regs: Registers;
  611. begin
  612. Regs.AH := $65;
  613. Regs.AL := InfoId;
  614. Regs.BX := CodePage;
  615. Regs.DX := CountryId;
  616. Regs.ES := tb div 16;
  617. Regs.DI := tb and 15;
  618. Regs.CX := SizeOf(TCountryInfo);
  619. RealIntr($21, Regs);
  620. DosMemGet(tb div 16,
  621. tb and 15,
  622. CountryInfo, Regs.CX );
  623. end;
  624. procedure InitAnsi;
  625. var
  626. CountryInfo: TCountryInfo; i: integer;
  627. begin
  628. { Fill table entries 0 to 127 }
  629. for i := 0 to 96 do
  630. UpperCaseTable[i] := chr(i);
  631. for i := 97 to 122 do
  632. UpperCaseTable[i] := chr(i - 32);
  633. for i := 123 to 127 do
  634. UpperCaseTable[i] := chr(i);
  635. for i := 0 to 64 do
  636. LowerCaseTable[i] := chr(i);
  637. for i := 65 to 90 do
  638. LowerCaseTable[i] := chr(i + 32);
  639. for i := 91 to 255 do
  640. LowerCaseTable[i] := chr(i);
  641. { Get country and codepage info }
  642. GetExtendedCountryInfo(1, $FFFF, $FFFF, CountryInfo);
  643. if CountryInfo.CodePage = 850 then
  644. begin
  645. { Special, known case }
  646. Move(CP850UCT, UpperCaseTable[128], 128);
  647. Move(CP850LCT, LowerCaseTable[128], 128);
  648. end
  649. else
  650. begin
  651. { this needs to be checked !!
  652. this is correct only if UpperCaseTable is
  653. and Offset:Segment word record (PM) }
  654. { get the uppercase table from dosmemory }
  655. GetExtendedCountryInfo(2, $FFFF, $FFFF, CountryInfo);
  656. DosMemGet(CountryInfo.UpperCaseTable shr 16, 2 + CountryInfo.UpperCaseTable and 65535, UpperCaseTable[128], 128);
  657. for i := 128 to 255 do
  658. begin
  659. if UpperCaseTable[i] <> chr(i) then
  660. LowerCaseTable[ord(UpperCaseTable[i])] := chr(i);
  661. end;
  662. end;
  663. end;
  664. Procedure InitInternational;
  665. begin
  666. InitInternationalGeneric;
  667. InitAnsi;
  668. end;
  669. function SysErrorMessage(ErrorCode: Integer): String;
  670. begin
  671. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  672. end;
  673. {****************************************************************************
  674. Os utils
  675. ****************************************************************************}
  676. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  677. begin
  678. Result:=FPCGetEnvVarFromP(envp,EnvVar);
  679. end;
  680. Function GetEnvironmentVariableCount : Integer;
  681. begin
  682. Result:=FPCCountEnvVar(EnvP);
  683. end;
  684. Function GetEnvironmentString(Index : Integer) : String;
  685. begin
  686. Result:=FPCGetEnvStrFromP(Envp,Index);
  687. end;
  688. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString;Flags:TExecuteFlags=[]):integer;
  689. var
  690. e : EOSError;
  691. CommandLine: AnsiString;
  692. begin
  693. dos.exec(path,comline);
  694. if (Dos.DosError <> 0) then
  695. begin
  696. if ComLine <> '' then
  697. CommandLine := Path + ' ' + ComLine
  698. else
  699. CommandLine := Path;
  700. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,Dos.DosError]);
  701. e.ErrorCode:=Dos.DosError;
  702. raise e;
  703. end;
  704. Result := DosExitCode;
  705. end;
  706. function ExecuteProcess (const Path: AnsiString;
  707. const ComLine: array of AnsiString;Flags:TExecuteFlags=[]): integer;
  708. var
  709. CommandLine: AnsiString;
  710. I: integer;
  711. begin
  712. Commandline := '';
  713. for I := 0 to High (ComLine) do
  714. if Pos (' ', ComLine [I]) <> 0 then
  715. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  716. else
  717. CommandLine := CommandLine + ' ' + Comline [I];
  718. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  719. end;
  720. {*************************************************************************
  721. Sleep (copied from crt.Delay)
  722. *************************************************************************}
  723. var
  724. DelayCnt : Longint;
  725. procedure Delayloop;assembler;
  726. asm
  727. .LDelayLoop1:
  728. subl $1,%eax
  729. jc .LDelayLoop2
  730. cmpl %fs:(%edi),%ebx
  731. je .LDelayLoop1
  732. .LDelayLoop2:
  733. end;
  734. procedure initdelay;assembler;
  735. asm
  736. pushl %ebx
  737. pushl %edi
  738. { for some reason, using int $31/ax=$901 doesn't work here }
  739. { and interrupts are always disabled at this point when }
  740. { running a program inside gdb(pas). Web bug 1345 (JM) }
  741. sti
  742. movl $0x46c,%edi
  743. movl $-28,%edx
  744. movl %fs:(%edi),%ebx
  745. .LInitDel1:
  746. cmpl %fs:(%edi),%ebx
  747. je .LInitDel1
  748. movl %fs:(%edi),%ebx
  749. movl %edx,%eax
  750. call DelayLoop
  751. notl %eax
  752. xorl %edx,%edx
  753. movl $55,%ecx
  754. divl %ecx
  755. movl %eax,DelayCnt
  756. popl %edi
  757. popl %ebx
  758. end;
  759. procedure Sleep(MilliSeconds: Cardinal);assembler;
  760. asm
  761. pushl %ebx
  762. pushl %edi
  763. movl MilliSeconds,%ecx
  764. jecxz .LDelay2
  765. movl $0x400,%edi
  766. movl DelayCnt,%edx
  767. movl %fs:(%edi),%ebx
  768. .LDelay1:
  769. movl %edx,%eax
  770. call DelayLoop
  771. loop .LDelay1
  772. .LDelay2:
  773. popl %edi
  774. popl %ebx
  775. end;
  776. {****************************************************************************
  777. Initialization code
  778. ****************************************************************************}
  779. Initialization
  780. InitExceptions; { Initialize exceptions. OS independent }
  781. InitInternational; { Initialize internationalization settings }
  782. InitDelay;
  783. Finalization
  784. DoneExceptions;
  785. end.