sysutils.pp 20 KB

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