sysutils.pp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2004-2005 by Olle Raab
  4. Sysutils unit for Mac OS.
  5. NOTE !!! THIS FILE IS UNDER CONSTRUCTION AND DOES NOT WORK CURRENLY.
  6. THUS IT IS NOT BUILT BY THE MAKEFILES
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. {$IFNDEF FPC_DOTTEDUNITS}
  14. unit sysutils;
  15. {$ENDIF FPC_DOTTEDUNITS}
  16. interface
  17. {$MODE objfpc}
  18. {$MODESWITCH OUT}
  19. {$IFDEF UNICODERTL}
  20. {$MODESWITCH UNICODESTRINGS}
  21. {$ELSE}
  22. {$H+}
  23. {$ENDIF}
  24. {$modeswitch typehelpers}
  25. {$modeswitch advancedrecords}
  26. {OS has only 1 byte version for ExecuteProcess}
  27. {$define executeprocuni}
  28. {$IFDEF FPC_DOTTEDUNITS}
  29. uses
  30. MacOSApi.MacOSTP;
  31. {$ELSE FPC_DOTTEDUNITS}
  32. uses
  33. MacOSTP;
  34. {$ENDIF FPC_DOTTEDUNITS}
  35. {$DEFINE HAS_SLEEP} {Dummy implementation: TODO }
  36. //{$DEFINE HAS_OSERROR} TODO
  37. //{$DEFINE HAS_OSCONFIG} TODO
  38. type
  39. //TODO Check pad and size
  40. //TODO unify with Dos.SearchRec
  41. PMacOSFindData = ^TMacOSFindData;
  42. TMacOSFindData = record
  43. {MacOS specific params, private, do not use:}
  44. paramBlock: CInfoPBRec;
  45. searchFSSpec: FSSpec;
  46. searchAttr: Byte; {attribute we are searching for}
  47. exactMatch: Boolean;
  48. end;
  49. { used OS file system APIs use ansistring }
  50. {$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
  51. { OS has an ansistring/single byte environment variable API }
  52. {$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
  53. { Include platform independent interface part }
  54. {$i sysutilh.inc}
  55. implementation
  56. {$IFDEF FPC_DOTTEDUNITS}
  57. uses
  58. TP.DOS, System.SysConst, MacOSApi.MacUtils; // For some included files.
  59. {$ELSE FPC_DOTTEDUNITS}
  60. uses
  61. Dos, Sysconst, macutils; // For some included files.
  62. {$ENDIF FPC_DOTTEDUNITS}
  63. {$DEFINE FPC_FEXPAND_VOLUMES}
  64. {$DEFINE FPC_FEXPAND_NO_DEFAULT_PATHS}
  65. {$DEFINE FPC_FEXPAND_DRIVESEP_IS_ROOT}
  66. {$DEFINE FPC_FEXPAND_NO_DOTS_UPDIR}
  67. {$DEFINE FPC_FEXPAND_NO_CURDIR}
  68. { Include platform independent implementation part }
  69. {$i sysutils.inc}
  70. {****************************************************************************
  71. File Functions
  72. ****************************************************************************}
  73. Function FileOpen (Const FileName : rawbytestring; Mode : Integer) : Longint;
  74. Var LinuxFlags : longint;
  75. SystemFileName: RawByteString;
  76. begin
  77. (* TODO fix
  78. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  79. LinuxFlags:=0;
  80. Case (Mode and 3) of
  81. 0 : LinuxFlags:=LinuxFlags or Open_RdOnly;
  82. 1 : LinuxFlags:=LinuxFlags or Open_WrOnly;
  83. 2 : LinuxFlags:=LinuxFlags or Open_RdWr;
  84. end;
  85. FileOpen:=fdOpen (FileName,LinuxFlags);
  86. //!! We need to set locking based on Mode !!
  87. *)
  88. end;
  89. Function FileCreate (Const FileName : RawByteString) : Longint;
  90. begin
  91. (* TODO fix
  92. FileCreate:=fdOpen(FileName,Open_RdWr or Open_Creat or Open_Trunc);
  93. *)
  94. end;
  95. Function FileCreate (Const FileName : RawByteString;Rights : Longint) : Longint;
  96. Var LinuxFlags : longint;
  97. BEGIN
  98. (* TODO fix
  99. LinuxFlags:=0;
  100. Case (Mode and 3) of
  101. 0 : LinuxFlags:=LinuxFlags or Open_RdOnly;
  102. 1 : LinuxFlags:=LinuxFlags or Open_WrOnly;
  103. 2 : LinuxFlags:=LinuxFlags or Open_RdWr;
  104. end;
  105. FileCreate:=fdOpen(FileName,LinuxFlags or Open_Creat or Open_Trunc);
  106. *)
  107. end;
  108. Function FileCreate (Const FileName : RawByteString;ShareMode : Longint; Rights : Longint) : Longint;
  109. Var LinuxFlags : longint;
  110. BEGIN
  111. (* TODO fix
  112. LinuxFlags:=0;
  113. Case (Mode and 3) of
  114. 0 : LinuxFlags:=LinuxFlags or Open_RdOnly;
  115. 1 : LinuxFlags:=LinuxFlags or Open_WrOnly;
  116. 2 : LinuxFlags:=LinuxFlags or Open_RdWr;
  117. end;
  118. FileCreate:=fdOpen(FileName,LinuxFlags or Open_Creat or Open_Trunc);
  119. *)
  120. end;
  121. Function FileRead (Handle : Longint; out Buffer; Count : longint) : Longint;
  122. begin
  123. (* TODO fix
  124. FileRead:=fdRead (Handle,Buffer,Count);
  125. *)
  126. end;
  127. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  128. begin
  129. (* TODO fix
  130. FileWrite:=fdWrite (Handle,Buffer,Count);
  131. *)
  132. end;
  133. Function FileSeek (Handle,FOffset,Origin : Longint) : Longint;
  134. begin
  135. (* TODO fix
  136. FileSeek:=fdSeek (Handle,FOffset,Origin);
  137. *)
  138. end;
  139. Function FileSeek (Handle : Longint; FOffset: Int64; Origin : Longint) : Int64;
  140. begin
  141. (* TODO fix
  142. {$warning need to add 64bit call }
  143. FileSeek:=fdSeek (Handle,FOffset,Origin);
  144. *)
  145. end;
  146. Procedure FileClose (Handle : Longint);
  147. begin
  148. (* TODO fix
  149. fdclose(Handle);
  150. *)
  151. end;
  152. Function FileTruncate (Handle: THandle; Size: Int64) : boolean;
  153. begin
  154. (* TODO fix
  155. FileTruncate:=fdtruncate(Handle,Size);
  156. *)
  157. end;
  158. Function FileAge (Const FileName : RawByteString): Int64;
  159. (*
  160. Var Info : Stat;
  161. Y,M,D,hh,mm,ss : word;
  162. *)
  163. begin
  164. (* TODO fix
  165. If not fstat (FileName,Info) then
  166. exit(-1)
  167. else
  168. begin
  169. EpochToLocal(info.mtime,y,m,d,hh,mm,ss);
  170. Result:=DateTimeToFileDate(EncodeDate(y,m,d)+EncodeTime(hh,mm,ss,0));
  171. end;
  172. *)
  173. end;
  174. function FileGetSymLinkTarget(const FileName: RawByteString; out SymLinkRec: TRawbyteSymLinkRec): Boolean;
  175. begin
  176. Result := False;
  177. end;
  178. Function FileExists (Const FileName : RawByteString; FollowLink : Boolean) : Boolean;
  179. (*
  180. Var Info : Stat;
  181. *)
  182. begin
  183. (* TODO fix
  184. FileExists:=fstat(filename,Info);
  185. *)
  186. end;
  187. Function DirectoryExists (Const Directory : RawByteString; FollowLink : Boolean) : Boolean;
  188. (*
  189. Var Info : Stat;
  190. *)
  191. begin
  192. (* TODO fix
  193. DirectoryExists:=fstat(Directory,Info) and
  194. ((info.mode and STAT_IFMT)=STAT_IFDIR);
  195. *)
  196. end;
  197. (*
  198. Function LinuxToWinAttr (FN : PAnsiChar; Const Info : Stat) : Longint;
  199. begin
  200. Result:=faArchive;
  201. If (Info.Mode and STAT_IFDIR)=STAT_IFDIR then
  202. Result:=Result or faDirectory;
  203. If (FN[0]='.') and (not (FN[1] in [#0,'.'])) then
  204. Result:=Result or faHidden;
  205. If (Info.Mode and STAT_IWUSR)=0 Then
  206. Result:=Result or faReadOnly;
  207. If (Info.Mode and
  208. (STAT_IFSOCK or STAT_IFBLK or STAT_IFCHR or STAT_IFIFO))<>0 then
  209. Result:=Result or faSysFile;
  210. end;
  211. {
  212. GlobToSearch takes a glob entry, stats the file.
  213. The glob entry is removed.
  214. If FileAttributes match, the entry is reused
  215. }
  216. Type
  217. TGlobSearchRec = Record
  218. Path : String;
  219. GlobHandle : PGlob;
  220. end;
  221. PGlobSearchRec = ^TGlobSearchRec;
  222. Function GlobToTSearchRec (Var Info : TSearchRec) : Boolean;
  223. Var SInfo : Stat;
  224. p : Pglob;
  225. GlobSearchRec : PGlobSearchrec;
  226. begin
  227. GlobSearchRec:=PGlobSearchrec(Info.FindHandle);
  228. P:=GlobSearchRec^.GlobHandle;
  229. Result:=P<>Nil;
  230. If Result then
  231. begin
  232. GlobSearchRec^.GlobHandle:=P^.Next;
  233. Result:=Fstat(GlobSearchRec^.Path+StrPas(p^.name),SInfo);
  234. If Result then
  235. begin
  236. Info.Attr:=LinuxToWinAttr(p^.name,SInfo);
  237. Result:=(Info.ExcludeAttr and Info.Attr)=0;
  238. If Result Then
  239. With Info do
  240. begin
  241. Attr:=Info.Attr;
  242. If P^.Name<>Nil then
  243. Name:=strpas(p^.name);
  244. Time:=Sinfo.mtime;
  245. Size:=Sinfo.Size;
  246. end;
  247. end;
  248. P^.Next:=Nil;
  249. GlobFree(P);
  250. end;
  251. end;
  252. *)
  253. procedure DoFind (var F: TSearchRec; var retname: RawByteString; firstTime: Boolean);
  254. var
  255. err: OSErr;
  256. s: Str255;
  257. begin
  258. (* TODO fix
  259. with Rslt, findData, paramBlock do
  260. begin
  261. ioVRefNum := searchFSSpec.vRefNum;
  262. if firstTime then
  263. ioFDirIndex := 0;
  264. while true do
  265. begin
  266. s := '';
  267. ioDirID := searchFSSpec.parID;
  268. ioFDirIndex := ioFDirIndex + 1;
  269. ioNamePtr := @s;
  270. err := PBGetCatInfoSync(@paramBlock);
  271. if err <> noErr then
  272. begin
  273. if err = fnfErr then
  274. DosError := 18
  275. else
  276. DosError := MacOSErr2RTEerr(err);
  277. break;
  278. end;
  279. attr := GetFileAttrFromPB(Rslt.paramBlock);
  280. if ((Attr and not(searchAttr)) = 0) then
  281. begin
  282. retname := s;
  283. SetCodePage(retname, DefaultFileSystemCodePage, false);
  284. UpperString(s, true);
  285. if FNMatch(Rslt.searchFSSpec.name, s) then
  286. begin
  287. size := GetFileSizeFromPB(paramBlock);
  288. time := MacTimeToDosPackedTime(ioFlMdDat);
  289. Result := 0;
  290. break;
  291. end;
  292. end;
  293. end;
  294. end;
  295. *)
  296. end;
  297. Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
  298. var
  299. s: Str255;
  300. begin
  301. (* TODO fix
  302. if path = '' then
  303. begin
  304. Result := 3;
  305. Exit;
  306. end;
  307. {We always also search for readonly and archive, regardless of Attr.}
  308. Rslt.searchAttr := (Attr or (archive or readonly));
  309. { TODO: convert PathArgToFSSpec (and the routines it calls) to rawbytestring }
  310. Result := PathArgToFSSpec(path, Rslt.searchFSSpec);
  311. with Rslt do
  312. if (Result = 0) or (Result = 2) then
  313. begin
  314. { FIXME: SearchSpec is a shortstring -> ignores encoding }
  315. SearchSpec := path;
  316. NamePos := Length(path) - Length(searchFSSpec.name);
  317. if (Pos('?', searchFSSpec.name) = 0) and (Pos('*', searchFSSpec.name) = 0) then {No wildcards}
  318. begin {If exact match, we don't have to scan the directory}
  319. exactMatch := true;
  320. Result := DoFindOne(searchFSSpec, paramBlock);
  321. if Result = 0 then
  322. begin
  323. Attr := GetFileAttrFromPB(paramBlock);
  324. if ((Attr and not(searchAttr)) = 0) then
  325. begin
  326. name := searchFSSpec.name;
  327. SetCodePage(name, DefaultFileSystemCodePage, false);
  328. size := GetFileSizeFromPB(paramBlock);
  329. time := MacTimeToDosPackedTime(paramBlock.ioFlMdDat);
  330. end
  331. else
  332. Result := 18;
  333. end
  334. else if Result = 2 then
  335. Result := 18;
  336. end
  337. else
  338. begin
  339. exactMatch := false;
  340. s := searchFSSpec.name;
  341. UpperString(s, true);
  342. Rslt.searchFSSpec.name := s;
  343. DoFind(Rslt, name, true);
  344. end;
  345. end;
  346. *)
  347. end;
  348. Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
  349. begin
  350. (* TODO fix
  351. if F.exactMatch then
  352. Result := 18
  353. else
  354. Result:=DoFind (Rslt, Name, false);
  355. *)
  356. end;
  357. Procedure InternalFindClose (var Handle: THandle; var FindData: TFindData);
  358. (*
  359. Var
  360. GlobSearchRec : PGlobSearchRec;
  361. *)
  362. begin
  363. (* TODO fix
  364. GlobSearchRec:=PGlobSearchRec(Handle);
  365. GlobFree (GlobSearchRec^.GlobHandle);
  366. Dispose(GlobSearchRec);
  367. *)
  368. end;
  369. Function FileGetDate (Handle : Longint) : Int64;
  370. (*
  371. Var Info : Stat;
  372. *)
  373. begin
  374. (* TODO fix
  375. If Not(FStat(Handle,Info)) then
  376. Result:=-1
  377. else
  378. Result:=Info.Mtime;
  379. *)
  380. end;
  381. Function FileSetDate (Handle: Longint; Age: Int64) : Longint;
  382. begin
  383. // TODO fix
  384. // Impossible under Linux from FileHandle !!
  385. FileSetDate:=-1;
  386. end;
  387. Function FileGetAttr (Const FileName : RawByteString) : Longint;
  388. (*
  389. Var Info : Stat;
  390. *)
  391. begin
  392. (* TODO fix
  393. If Not FStat (FileName,Info) then
  394. Result:=-1
  395. Else
  396. Result:=LinuxToWinAttr(PAnsiChar(FileName),Info);
  397. *)
  398. end;
  399. Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
  400. begin
  401. Result:=-1;
  402. end;
  403. Function DeleteFile (Const FileName : RawByteString) : Boolean;
  404. begin
  405. (* TODO fix
  406. Result:=UnLink (FileName);
  407. *)
  408. end;
  409. Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;
  410. begin
  411. (* TODO fix
  412. RenameFile:=Unix.FRename(OldNAme,NewName);
  413. *)
  414. end;
  415. {****************************************************************************
  416. Disk Functions
  417. ****************************************************************************}
  418. {
  419. The Diskfree and Disksize functions need a file on the specified drive, since this
  420. is required for the statfs system call.
  421. These filenames are set in drivestr[0..26], and have been preset to :
  422. 0 - '.' (default drive - hence current dir is ok.)
  423. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  424. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  425. 3 - '/' (C: equivalent of dos is the root partition)
  426. 4..26 (can be set by you're own applications)
  427. ! Use AddDisk() to Add new drives !
  428. They both return -1 when a failure occurs.
  429. }
  430. Const
  431. FixDriveStr : array[0..3] of PAnsiChar=(
  432. '.',
  433. '/fd0/.',
  434. '/fd1/.',
  435. '/.'
  436. );
  437. var
  438. Drives : byte;
  439. DriveStr : array[4..26] of PAnsiChar;
  440. Procedure AddDisk(const path:string);
  441. begin
  442. if not (DriveStr[Drives]=nil) then
  443. FreeMem(DriveStr[Drives],StrLen(DriveStr[Drives])+1);
  444. GetMem(DriveStr[Drives],length(Path)+1);
  445. StrPCopy(DriveStr[Drives],path);
  446. inc(Drives);
  447. if Drives>26 then
  448. Drives:=4;
  449. end;
  450. Function DiskFree(Drive: Byte): int64;
  451. (*
  452. var
  453. fs : tstatfs;
  454. *)
  455. Begin
  456. (* TODO fix
  457. if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and statfs(StrPas(fixdrivestr[drive]),fs)) or
  458. ((not (drivestr[Drive]=nil)) and statfs(StrPas(drivestr[drive]),fs)) then
  459. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  460. else
  461. Diskfree:=-1;
  462. *)
  463. End;
  464. Function DiskSize(Drive: Byte): int64;
  465. (*
  466. var
  467. fs : tstatfs;
  468. *)
  469. Begin
  470. (* TODO fix
  471. if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and statfs(StrPas(fixdrivestr[drive]),fs)) or
  472. ((not (drivestr[Drive]=nil)) and statfs(StrPas(drivestr[drive]),fs)) then
  473. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  474. else
  475. DiskSize:=-1;
  476. *)
  477. End;
  478. {****************************************************************************
  479. Locale Functions
  480. ****************************************************************************}
  481. Procedure GetLocalTime(var SystemTime: TSystemTime);
  482. begin
  483. (* TODO fix
  484. Unix.GetTime(SystemTime.Hour, SystemTime.Minute, SystemTime.Second);
  485. Unix.GetDate(SystemTime.Year, SystemTime.Month, SystemTime.Day);
  486. SystemTime.MilliSecond := 0;
  487. *)
  488. end ;
  489. Procedure InitAnsi;
  490. Var
  491. i : longint;
  492. begin
  493. { Fill table entries 0 to 127 }
  494. for i := 0 to 96 do
  495. UpperCaseTable[i] := chr(i);
  496. for i := 97 to 122 do
  497. UpperCaseTable[i] := chr(i - 32);
  498. for i := 123 to 191 do
  499. UpperCaseTable[i] := chr(i);
  500. Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  501. for i := 0 to 64 do
  502. LowerCaseTable[i] := chr(i);
  503. for i := 65 to 90 do
  504. LowerCaseTable[i] := chr(i + 32);
  505. for i := 91 to 191 do
  506. LowerCaseTable[i] := chr(i);
  507. Move (CPISO88591LCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  508. end;
  509. Procedure InitInternational;
  510. begin
  511. InitInternationalGeneric;
  512. InitAnsi;
  513. end;
  514. function SysErrorMessage(ErrorCode: Integer): String;
  515. begin
  516. (* TODO fix
  517. Result:=StrError(ErrorCode);
  518. *)
  519. end;
  520. {****************************************************************************
  521. OS utility functions
  522. ****************************************************************************}
  523. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  524. begin
  525. (* TODO fix
  526. Result:=Unix.Getenv(PAnsiChar(EnvVar));
  527. *)
  528. end;
  529. Function GetEnvironmentVariableCount : Integer;
  530. begin
  531. // Result:=FPCCountEnvVar(EnvP);
  532. Result:=0;
  533. end;
  534. Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
  535. begin
  536. // Result:=FPCGetEnvStrFromP(Envp,Index);
  537. Result:='';
  538. end;
  539. { Create a DoScript AppleEvent that targets the given application with text as the direct object. }
  540. function CreateDoScriptEvent (applCreator: OSType; scriptText: PAnsiChar; var theEvent: AppleEvent): OSErr;
  541. var
  542. err: OSErr;
  543. targetAddress: AEDesc;
  544. s: signedByte;
  545. begin
  546. err := AECreateDesc(FourCharCodeToLongword(typeApplSignature), @applCreator, sizeof(applCreator), targetAddress);
  547. if err = noErr then
  548. begin
  549. err := AECreateAppleEvent(FourCharCodeToLongword('misc'), FourCharCodeToLongword('dosc'),
  550. targetAddress, kAutoGenerateReturnID, kAnyTransactionID, theEvent);
  551. if err = noErr then
  552. { Add script text as the direct object parameter. }
  553. err := AEPutParamPtr(theEvent, FourCharCodeToLongword('----'),
  554. FourCharCodeToLongword('TEXT'), scriptText, Length(scriptText));
  555. if err <> noErr then
  556. AEDisposeDesc(theEvent);
  557. AEDisposeDesc(targetAddress);
  558. end;
  559. CreateDoScriptEvent := err;
  560. end;
  561. Procedure Fpc_WriteBuffer(var f:Text;const b;len:longint);[external name 'FPC_WRITEBUFFER'];
  562. {declared in text.inc}
  563. procedure WriteAEDescTypeCharToFile(desc: AEDesc; var f: Text);
  564. begin
  565. if desc.descriptorType = FourCharCodeToLongword(typeChar) then
  566. begin
  567. HLock(desc.dataHandle);
  568. Fpc_WriteBuffer(f, PAnsiChar(desc.dataHandle^)^, GetHandleSize(desc.dataHandle));
  569. Flush(f);
  570. HUnLock(desc.dataHandle);
  571. end;
  572. end;
  573. function ExecuteToolserverScript(scriptText: PAnsiChar; var statusCode: Longint): OSErr;
  574. var
  575. err: OSErr;
  576. err2: OSErr; {Non serious error}
  577. theEvent: AppleEvent;
  578. reply: AppleEvent;
  579. aresult: AEDesc;
  580. applFileSpec: FSSpec;
  581. p: SignedByte;
  582. const
  583. applCreator = 'MPSX'; {Toolserver}
  584. begin
  585. statusCode:= 3; //3 according to MPW.
  586. err:= CreateDoScriptEvent (FourCharCodeToLongword(applCreator), scriptText, theEvent);
  587. if err = noErr then
  588. begin
  589. err := AESend(theEvent, reply, kAEWaitReply, kAENormalPriority, kAEDefaultTimeOut, nil, nil);
  590. if err = connectionInvalid then { Toolserver not available }
  591. begin
  592. err := FindApplication(FourCharCodeToLongword(applCreator), applFileSpec);
  593. if err = noErr then
  594. err := LaunchFSSpec(false, applFileSpec);
  595. if err = noErr then
  596. err := AESend(theEvent, reply, kAEWaitReply, kAENormalPriority, kAEDefaultTimeOut, nil, nil);
  597. end;
  598. if err = noErr then
  599. begin
  600. err:= AEGetParamDesc(reply, FourCharCodeToLongword('stat'),
  601. FourCharCodeToLongword(typeLongInteger), aresult);
  602. if err = noErr then
  603. if aresult.descriptorType = FourCharCodeToLongword(typeLongInteger) then
  604. statusCode:= LongintPtr(aresult.dataHandle^)^;
  605. {If there is no output below, we get a non zero error code}
  606. err2:= AEGetParamDesc(reply, FourCharCodeToLongword('----'),
  607. FourCharCodeToLongword(typeChar), aresult);
  608. if err2 = noErr then
  609. WriteAEDescTypeCharToFile(aresult, stdout);
  610. err2:= AEGetParamDesc(reply, FourCharCodeToLongword('diag'),
  611. FourCharCodeToLongword(typeChar), aresult);
  612. if err2 = noErr then
  613. WriteAEDescTypeCharToFile(aresult, stderr);
  614. AEDisposeDesc(reply);
  615. {$IFDEF TARGET_API_MAC_CARBON }
  616. {$ERROR FIXME AEDesc data is not allowed to be directly accessed}
  617. {$ENDIF}
  618. end;
  619. AEDisposeDesc(theEvent);
  620. end;
  621. ExecuteToolserverScript:= err;
  622. end;
  623. function ExecuteProcess (const Path: RawByteString; const ComLine: RawByteString;Flags:TExecuteFlags=[]):
  624. integer;
  625. var
  626. s: AnsiString;
  627. wdpath: RawByteString;
  628. laststatuscode : longint;
  629. E: EOSError;
  630. Begin
  631. {Make ToolServers working directory in sync with our working directory}
  632. PathArgToFullPath(':', wdpath);
  633. wdpath:= 'Directory ' + wdpath;
  634. Result := ExecuteToolserverScript(PAnsiChar(wdpath), laststatuscode);
  635. {TODO Only change path when actually needed. But this requires some
  636. change counter to be incremented each time wd is changed. }
  637. s:= path + ' ' + comline;
  638. Result := ExecuteToolserverScript(PAnsiChar(s), laststatuscode);
  639. if Result = afpItemNotFound then
  640. Result := 900
  641. else
  642. Result := MacOSErr2RTEerr(Result);
  643. if Result <> 0 then
  644. begin
  645. E := EOSError.CreateFmt (SExecuteProcessFailed, [Comline, DosError]);
  646. E.ErrorCode := DosError;
  647. raise E;
  648. end;
  649. //TODO Better dos error codes
  650. if laststatuscode <> 0 then
  651. begin
  652. {MPW status might be 24 bits}
  653. Result := laststatuscode and $ffff;
  654. if Result = 0 then
  655. Result := 1;
  656. end
  657. else
  658. Result := 0;
  659. End;
  660. function ExecuteProcess (const Path: RawByteString;
  661. const ComLine: array of RawByteString;Flags:TExecuteFlags=[]): integer;
  662. var
  663. CommandLine: RawByteString;
  664. I: integer;
  665. begin
  666. Commandline := '';
  667. for I := 0 to High (ComLine) do
  668. if Pos (' ', ComLine [I]) <> 0 then
  669. CommandLine := CommandLine + ' ' + '"' + ToSingleByteFileSystemEncodedFileName(ComLine [I]) + '"'
  670. else
  671. CommandLine := CommandLine + ' ' + ToSingleByteFileSystemEncodedFileName(Comline [I]);
  672. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  673. end;
  674. procedure C_usleep(val : uint32); external 'StdCLib' name 'usleep';
  675. procedure Sleep(milliseconds: Cardinal);
  676. begin
  677. C_usleep(milliseconds*1000);
  678. end;
  679. (*
  680. Function GetLastOSError : Integer;
  681. begin
  682. end;
  683. *)
  684. {****************************************************************************
  685. Initialization code
  686. ****************************************************************************}
  687. Initialization
  688. InitExceptions; { Initialize exceptions. OS independent }
  689. InitInternational; { Initialize internationalization settings }
  690. Finalization
  691. FreeTerminateProcs;
  692. DoneExceptions;
  693. end.