sysutils.pp 20 KB

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