sysutils.pp 20 KB

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