sysutils.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  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. var
  247. L: longint;
  248. begin
  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: string): boolean;
  259. var
  260. L: longint;
  261. begin
  262. if Directory = '' then
  263. Result := false
  264. else
  265. begin
  266. if ((Length (Directory) = 2) or
  267. (Length (Directory) = 3) and
  268. (Directory [3] in AllowDirectorySeparators)) and
  269. (Directory [2] in AllowDriveSeparators) and
  270. (UpCase (Directory [1]) in ['A'..'Z']) then
  271. (* Checking attributes for 'x:' is not possible but for 'x:.' it is. *)
  272. L := FileGetAttr (Directory + '.')
  273. else if (Directory [Length (Directory)] in AllowDirectorySeparators) and
  274. (Length (Directory) > 1) and
  275. (* Do not remove '\' in '\\' (invalid path, possibly broken UNC path). *)
  276. not (Directory [Length (Directory) - 1] in AllowDirectorySeparators) then
  277. L := FileGetAttr (Copy (Directory, 1, Length (Directory) - 1))
  278. else
  279. L := FileGetAttr (Directory);
  280. Result := (L > 0) and (L and faDirectory = faDirectory);
  281. end;
  282. end;
  283. Function FindFirst (Const Path : String; Attr : Longint; out Rslt : TSearchRec) : Longint;
  284. Var Sr : PSearchrec;
  285. begin
  286. //!! Sr := New(PSearchRec);
  287. getmem(sr,sizeof(searchrec));
  288. Rslt.FindHandle := longint(Sr);
  289. DOS.FindFirst(Path, Attr, Sr^);
  290. result := -DosError;
  291. if result = 0 then
  292. begin
  293. Rslt.Time := Sr^.Time;
  294. Rslt.Size := Sr^.Size;
  295. Rslt.Attr := Sr^.Attr;
  296. Rslt.ExcludeAttr := 0;
  297. Rslt.Name := Sr^.Name;
  298. end ;
  299. end;
  300. Function FindNext (Var Rslt : TSearchRec) : Longint;
  301. var
  302. Sr: PSearchRec;
  303. begin
  304. Sr := PSearchRec(Rslt.FindHandle);
  305. if Sr <> nil then
  306. begin
  307. DOS.FindNext(Sr^);
  308. result := -DosError;
  309. if result = 0 then
  310. begin
  311. Rslt.Time := Sr^.Time;
  312. Rslt.Size := Sr^.Size;
  313. Rslt.Attr := Sr^.Attr;
  314. Rslt.ExcludeAttr := 0;
  315. Rslt.Name := Sr^.Name;
  316. end;
  317. end;
  318. end;
  319. Procedure FindClose (Var F : TSearchrec);
  320. var
  321. Sr: PSearchRec;
  322. begin
  323. Sr := PSearchRec(F.FindHandle);
  324. if Sr <> nil then
  325. begin
  326. //!! Dispose(Sr);
  327. // This call is non dummy if LFNSupport is true PM
  328. DOS.FindClose(SR^);
  329. freemem(sr,sizeof(searchrec));
  330. end;
  331. F.FindHandle := 0;
  332. end;
  333. Function FileGetDate (Handle : Longint) : Longint;
  334. var
  335. Regs: registers;
  336. begin
  337. //!! for win95 an alternative function is available.
  338. Regs.Ebx := Handle;
  339. Regs.Eax := $5700;
  340. RealIntr($21, Regs);
  341. if Regs.Flags and CarryFlag <> 0 then
  342. result := -1
  343. else
  344. begin
  345. LongRec(result).Lo := Regs.cx;
  346. LongRec(result).Hi := Regs.dx;
  347. end ;
  348. end;
  349. Function FileSetDate (Handle, Age : Longint) : Longint;
  350. var
  351. Regs: registers;
  352. begin
  353. Regs.Ebx := Handle;
  354. Regs.Eax := $5701;
  355. Regs.Ecx := Lo(Age);
  356. Regs.Edx := Hi(Age);
  357. RealIntr($21, Regs);
  358. if Regs.Flags and CarryFlag <> 0 then
  359. result := -Regs.Ax
  360. else
  361. result := 0;
  362. end;
  363. Function FileGetAttr (Const FileName : String) : Longint;
  364. var
  365. Regs: registers;
  366. begin
  367. StringToTB(FileName);
  368. Regs.Edx := tb_offset;
  369. Regs.Ds := tb_segment;
  370. if LFNSupport then
  371. begin
  372. Regs.Ax := $7143;
  373. Regs.Bx := 0;
  374. end
  375. else
  376. Regs.Ax := $4300;
  377. RealIntr($21, Regs);
  378. if Regs.Flags and CarryFlag <> 0 then
  379. result := -1
  380. else
  381. result := Regs.Cx;
  382. end;
  383. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  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. begin
  392. Regs.Ax := $7143;
  393. Regs.Bx := 1;
  394. end
  395. else
  396. Regs.Ax := $4301;
  397. Regs.Cx := Attr;
  398. RealIntr($21, Regs);
  399. if Regs.Flags and CarryFlag <> 0 then
  400. result := -Regs.Ax
  401. else
  402. result := 0;
  403. end;
  404. Function DeleteFile (Const FileName : String) : Boolean;
  405. var
  406. Regs: registers;
  407. begin
  408. StringToTB(FileName);
  409. Regs.Edx := tb_offset;
  410. Regs.Ds := tb_segment;
  411. if LFNSupport then
  412. Regs.Eax := $7141
  413. else
  414. Regs.Eax := $4100;
  415. Regs.Esi := 0;
  416. Regs.Ecx := 0;
  417. RealIntr($21, Regs);
  418. result := (Regs.Flags and CarryFlag = 0);
  419. end;
  420. Function RenameFile (Const OldName, NewName : String) : Boolean;
  421. var
  422. Regs: registers;
  423. begin
  424. StringToTB(OldName + #0 + NewName);
  425. Regs.Edx := tb_offset;
  426. Regs.Ds := tb_segment;
  427. Regs.Edi := tb_offset + Length(OldName) + 1;
  428. Regs.Es := tb_segment;
  429. if LFNSupport then
  430. Regs.Eax := $7156
  431. else
  432. Regs.Eax := $5600;
  433. Regs.Ecx := $ff;
  434. RealIntr($21, Regs);
  435. result := (Regs.Flags and CarryFlag = 0);
  436. end;
  437. {****************************************************************************
  438. Disk Functions
  439. ****************************************************************************}
  440. TYPE ExtendedFat32FreeSpaceRec=packed Record
  441. RetSize : WORD; { (ret) size of returned structure}
  442. Strucversion : WORD; {(call) structure version (0000h)
  443. (ret) actual structure version (0000h)}
  444. SecPerClus, {number of sectors per cluster}
  445. BytePerSec, {number of bytes per sector}
  446. AvailClusters, {number of available clusters}
  447. TotalClusters, {total number of clusters on the drive}
  448. AvailPhysSect, {physical sectors available on the drive}
  449. TotalPhysSect, {total physical sectors on the drive}
  450. AvailAllocUnits, {Available allocation units}
  451. TotalAllocUnits : DWORD; {Total allocation units}
  452. Dummy,Dummy2 : DWORD; {8 bytes reserved}
  453. END;
  454. function do_diskdata(drive : byte; Free : BOOLEAN) : Int64;
  455. VAR S : String;
  456. Rec : ExtendedFat32FreeSpaceRec;
  457. regs : registers;
  458. procedure OldDosDiskData;
  459. begin
  460. regs.dl:=drive;
  461. regs.ah:=$36;
  462. msdos(regs);
  463. if regs.ax<>$FFFF then
  464. begin
  465. if Free then
  466. Do_DiskData:=int64(regs.ax)*regs.bx*regs.cx
  467. else
  468. Do_DiskData:=int64(regs.ax)*regs.cx*regs.dx;
  469. end
  470. else
  471. do_diskdata:=-1;
  472. end;
  473. BEGIN
  474. if LFNSupport then
  475. begin
  476. S:='C:\'#0;
  477. if Drive=0 then
  478. begin
  479. GetDir(Drive,S);
  480. Setlength(S,4);
  481. S[4]:=#0;
  482. end
  483. else
  484. S[1]:=chr(Drive+64);
  485. Rec.Strucversion:=0;
  486. Rec.RetSize := 0;
  487. dosmemput(tb_segment,tb_offset,Rec,SIZEOF(ExtendedFat32FreeSpaceRec));
  488. dosmemput(tb_segment,tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1,S[1],4);
  489. regs.dx:=tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1;
  490. regs.ds:=tb_segment;
  491. regs.di:=tb_offset;
  492. regs.es:=tb_segment;
  493. regs.cx:=Sizeof(ExtendedFat32FreeSpaceRec);
  494. regs.ax:=$7303;
  495. msdos(regs);
  496. if (regs.flags and fcarry) = 0 then {No error clausule in int except cf}
  497. begin
  498. copyfromdos(rec,Sizeof(ExtendedFat32FreeSpaceRec));
  499. if Rec.RetSize = 0 then (* Error - "FAT32" function not supported! *)
  500. OldDosDiskData
  501. else
  502. if Free then
  503. Do_DiskData:=int64(rec.AvailAllocUnits)*rec.SecPerClus*rec.BytePerSec
  504. else
  505. Do_DiskData:=int64(rec.TotalAllocUnits)*rec.SecPerClus*rec.BytePerSec;
  506. end
  507. else
  508. Do_DiskData:=-1;
  509. end
  510. else
  511. OldDosDiskData;
  512. end;
  513. function diskfree(drive : byte) : int64;
  514. begin
  515. diskfree:=Do_DiskData(drive,TRUE);
  516. end;
  517. function disksize(drive : byte) : int64;
  518. begin
  519. disksize:=Do_DiskData(drive,false);
  520. end;
  521. Function GetCurrentDir : String;
  522. begin
  523. GetDir(0, result);
  524. end;
  525. Function SetCurrentDir (Const NewDir : String) : Boolean;
  526. begin
  527. {$I-}
  528. ChDir(NewDir);
  529. {$I+}
  530. result := (IOResult = 0);
  531. end;
  532. Function CreateDir (Const NewDir : String) : Boolean;
  533. begin
  534. {$I-}
  535. MkDir(NewDir);
  536. {$I+}
  537. result := (IOResult = 0);
  538. end;
  539. Function RemoveDir (Const Dir : String) : Boolean;
  540. begin
  541. {$I-}
  542. RmDir(Dir);
  543. {$I+}
  544. result := (IOResult = 0);
  545. end;
  546. {****************************************************************************
  547. Time Functions
  548. ****************************************************************************}
  549. Procedure GetLocalTime(var SystemTime: TSystemTime);
  550. var
  551. Regs: Registers;
  552. begin
  553. Regs.ah := $2C;
  554. RealIntr($21, Regs);
  555. SystemTime.Hour := Regs.Ch;
  556. SystemTime.Minute := Regs.Cl;
  557. SystemTime.Second := Regs.Dh;
  558. SystemTime.MilliSecond := Regs.Dl*10;
  559. Regs.ah := $2A;
  560. RealIntr($21, Regs);
  561. SystemTime.Year := Regs.Cx;
  562. SystemTime.Month := Regs.Dh;
  563. SystemTime.Day := Regs.Dl;
  564. end ;
  565. {****************************************************************************
  566. Misc Functions
  567. ****************************************************************************}
  568. procedure Beep;
  569. begin
  570. end;
  571. {****************************************************************************
  572. Locale Functions
  573. ****************************************************************************}
  574. { Codepage constants }
  575. const
  576. CP_US = 437;
  577. CP_MultiLingual = 850;
  578. CP_SlavicLatin2 = 852;
  579. CP_Turkish = 857;
  580. CP_Portugal = 860;
  581. CP_IceLand = 861;
  582. CP_Canada = 863;
  583. CP_NorwayDenmark = 865;
  584. { CountryInfo }
  585. type
  586. TCountryInfo = packed record
  587. InfoId: byte;
  588. case integer of
  589. 1: ( Size: word;
  590. CountryId: word;
  591. CodePage: word;
  592. CountryInfo: array[0..33] of byte );
  593. 2: ( UpperCaseTable: longint );
  594. 4: ( FilenameUpperCaseTable: longint );
  595. 5: ( FilecharacterTable: longint );
  596. 6: ( CollatingTable: longint );
  597. 7: ( DBCSLeadByteTable: longint );
  598. end ;
  599. procedure GetExtendedCountryInfo(InfoId: integer; CodePage, CountryId: word; var CountryInfo: TCountryInfo);
  600. Var Regs: Registers;
  601. begin
  602. Regs.AH := $65;
  603. Regs.AL := InfoId;
  604. Regs.BX := CodePage;
  605. Regs.DX := CountryId;
  606. Regs.ES := tb div 16;
  607. Regs.DI := tb and 15;
  608. Regs.CX := SizeOf(TCountryInfo);
  609. RealIntr($21, Regs);
  610. DosMemGet(tb div 16,
  611. tb and 15,
  612. CountryInfo, Regs.CX );
  613. end;
  614. procedure InitAnsi;
  615. var
  616. CountryInfo: TCountryInfo; i: integer;
  617. begin
  618. { Fill table entries 0 to 127 }
  619. for i := 0 to 96 do
  620. UpperCaseTable[i] := chr(i);
  621. for i := 97 to 122 do
  622. UpperCaseTable[i] := chr(i - 32);
  623. for i := 123 to 127 do
  624. UpperCaseTable[i] := chr(i);
  625. for i := 0 to 64 do
  626. LowerCaseTable[i] := chr(i);
  627. for i := 65 to 90 do
  628. LowerCaseTable[i] := chr(i + 32);
  629. for i := 91 to 255 do
  630. LowerCaseTable[i] := chr(i);
  631. { Get country and codepage info }
  632. GetExtendedCountryInfo(1, $FFFF, $FFFF, CountryInfo);
  633. if CountryInfo.CodePage = 850 then
  634. begin
  635. { Special, known case }
  636. Move(CP850UCT, UpperCaseTable[128], 128);
  637. Move(CP850LCT, LowerCaseTable[128], 128);
  638. end
  639. else
  640. begin
  641. { this needs to be checked !!
  642. this is correct only if UpperCaseTable is
  643. and Offset:Segment word record (PM) }
  644. { get the uppercase table from dosmemory }
  645. GetExtendedCountryInfo(2, $FFFF, $FFFF, CountryInfo);
  646. DosMemGet(CountryInfo.UpperCaseTable shr 16, 2 + CountryInfo.UpperCaseTable and 65535, UpperCaseTable[128], 128);
  647. for i := 128 to 255 do
  648. begin
  649. if UpperCaseTable[i] <> chr(i) then
  650. LowerCaseTable[ord(UpperCaseTable[i])] := chr(i);
  651. end;
  652. end;
  653. end;
  654. Procedure InitInternational;
  655. begin
  656. InitInternationalGeneric;
  657. InitAnsi;
  658. end;
  659. function SysErrorMessage(ErrorCode: Integer): String;
  660. begin
  661. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  662. end;
  663. {****************************************************************************
  664. Os utils
  665. ****************************************************************************}
  666. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  667. begin
  668. Result:=FPCGetEnvVarFromP(envp,EnvVar);
  669. end;
  670. Function GetEnvironmentVariableCount : Integer;
  671. begin
  672. Result:=FPCCountEnvVar(EnvP);
  673. end;
  674. Function GetEnvironmentString(Index : Integer) : String;
  675. begin
  676. Result:=FPCGetEnvStrFromP(Envp,Index);
  677. end;
  678. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString;Flags:TExecuteFlags=[]):integer;
  679. var
  680. e : EOSError;
  681. CommandLine: AnsiString;
  682. begin
  683. dos.exec(path,comline);
  684. if (Dos.DosError <> 0) then
  685. begin
  686. if ComLine <> '' then
  687. CommandLine := Path + ' ' + ComLine
  688. else
  689. CommandLine := Path;
  690. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,Dos.DosError]);
  691. e.ErrorCode:=Dos.DosError;
  692. raise e;
  693. end;
  694. Result := DosExitCode;
  695. end;
  696. function ExecuteProcess (const Path: AnsiString;
  697. const ComLine: array of AnsiString;Flags:TExecuteFlags=[]): integer;
  698. var
  699. CommandLine: AnsiString;
  700. I: integer;
  701. begin
  702. Commandline := '';
  703. for I := 0 to High (ComLine) do
  704. if Pos (' ', ComLine [I]) <> 0 then
  705. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  706. else
  707. CommandLine := CommandLine + ' ' + Comline [I];
  708. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  709. end;
  710. {*************************************************************************
  711. Sleep (copied from crt.Delay)
  712. *************************************************************************}
  713. var
  714. DelayCnt : Longint;
  715. procedure Delayloop;assembler;
  716. asm
  717. .LDelayLoop1:
  718. subl $1,%eax
  719. jc .LDelayLoop2
  720. cmpl %fs:(%edi),%ebx
  721. je .LDelayLoop1
  722. .LDelayLoop2:
  723. end;
  724. procedure initdelay;assembler;
  725. asm
  726. pushl %ebx
  727. pushl %edi
  728. { for some reason, using int $31/ax=$901 doesn't work here }
  729. { and interrupts are always disabled at this point when }
  730. { running a program inside gdb(pas). Web bug 1345 (JM) }
  731. sti
  732. movl $0x46c,%edi
  733. movl $-28,%edx
  734. movl %fs:(%edi),%ebx
  735. .LInitDel1:
  736. cmpl %fs:(%edi),%ebx
  737. je .LInitDel1
  738. movl %fs:(%edi),%ebx
  739. movl %edx,%eax
  740. call DelayLoop
  741. notl %eax
  742. xorl %edx,%edx
  743. movl $55,%ecx
  744. divl %ecx
  745. movl %eax,DelayCnt
  746. popl %edi
  747. popl %ebx
  748. end;
  749. procedure Sleep(MilliSeconds: Cardinal);assembler;
  750. asm
  751. pushl %ebx
  752. pushl %edi
  753. movl MilliSeconds,%ecx
  754. jecxz .LDelay2
  755. movl $0x400,%edi
  756. movl DelayCnt,%edx
  757. movl %fs:(%edi),%ebx
  758. .LDelay1:
  759. movl %edx,%eax
  760. call DelayLoop
  761. loop .LDelay1
  762. .LDelay2:
  763. popl %edi
  764. popl %ebx
  765. end;
  766. {****************************************************************************
  767. Initialization code
  768. ****************************************************************************}
  769. Initialization
  770. InitExceptions; { Initialize exceptions. OS independent }
  771. InitInternational; { Initialize internationalization settings }
  772. InitDelay;
  773. Finalization
  774. DoneExceptions;
  775. end.