sysutils.pp 21 KB

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