sysutils.pp 21 KB

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