sysutils.pp 20 KB

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