sysutils.pp 20 KB

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