system.pp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2002-2004 by Olle Raab
  5. FreePascal system unit for MacOS.
  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 System;
  13. interface
  14. { include system-independent routine headers }
  15. {$I systemh.inc}
  16. {Platform specific information}
  17. type
  18. {$ifdef CPU64}
  19. THandle = Int64;
  20. {$else CPU64}
  21. THandle = Longint;
  22. {$endif CPU64}
  23. const
  24. LineEnding = #13;
  25. LFNSupport = true;
  26. DirectorySeparator = ':';
  27. DriveSeparator = ':';
  28. PathSeparator = ','; {Is used in MPW and OzTeX}
  29. FileNameCaseSensitive = false;
  30. maxExitCode = 65535;
  31. { include heap support headers }
  32. {$I heaph.inc}
  33. const
  34. { Default filehandles }
  35. UnusedHandle : Longint = -1;
  36. StdInputHandle : Longint = 0;
  37. StdOutputHandle : Longint = 1;
  38. StdErrorHandle : Longint = 2;
  39. sLineBreak = LineEnding;
  40. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCR;
  41. var
  42. argc : longint;
  43. argv : ppchar;
  44. envp : ppchar;
  45. {*********************************}
  46. {** MacOS specific functions **}
  47. {*********************************}
  48. {To be called at regular intervals, for lenghty tasks.
  49. Yield might give time for other tasks to run under the cooperative
  50. multitasked macos. For an MPW Tool, it also spinns the cursor.}
  51. procedure Yield;
  52. {To set mac file type and creator codes, to be used for files created
  53. by the FPC runtime library. They must be exactly 4 chars long.}
  54. procedure SetDefaultMacOSFiletype(ftype: ShortString);
  55. procedure SetDefaultMacOSCreator(creator: ShortString);
  56. {*********************************}
  57. {** Available features on macos **}
  58. {*********************************}
  59. var
  60. macosHasGestalt: Boolean;
  61. macosHasWaitNextEvent: Boolean;
  62. macosHasColorQD: Boolean;
  63. macosHasFPU: Boolean;
  64. macosSystemVersion: Integer;
  65. macosHasSysDebugger: Boolean = false;
  66. macosHasCFM: Boolean;
  67. macosHasAppleEvents: Boolean;
  68. macosHasAliasMgr: Boolean;
  69. macosHasFSSpec: Boolean;
  70. macosHasFindFolder: Boolean;
  71. macosHasScriptMgr: Boolean;
  72. macosNrOfScriptsInstalled: Integer;
  73. macosHasAppearance: Boolean;
  74. macosHasAppearance101: Boolean;
  75. macosHasAppearance11: Boolean;
  76. macosBootVolumeVRefNum: Integer;
  77. macosBootVolumeName: String[31];
  78. {
  79. MacOS paths
  80. ===========
  81. MacOS directory separator is a colon ":" which is the only character not
  82. allowed in filenames.
  83. A path containing no colon or which begins with a colon is a partial path.
  84. E g ":kalle:petter" ":kalle" "kalle"
  85. All other paths are full (absolute) paths. E g "HD:kalle:" "HD:"
  86. When generating paths, one is safe is one ensures that all partial paths
  87. begins with a colon, and all full paths ends with a colon.
  88. In full paths the first name (e g HD above) is the name of a mounted volume.
  89. These names are not unique, because, for instance, two diskettes with the
  90. same names could be inserted. This means that paths on MacOS is not
  91. waterproof. In case of equal names the first volume found will do.
  92. Two colons "::" are the relative path to the parent. Three is to the
  93. grandparent etc.
  94. }
  95. implementation
  96. {
  97. About the implementation
  98. ========================
  99. A MacOS application is assembled and linked by MPW (Macintosh
  100. Programmers Workshop), which nowadays is free to use. For info
  101. and download of MPW and MacOS api, see www.apple.com
  102. It can be linked to either a graphical user interface application,
  103. a standalone text only application (using SIOW) or
  104. to an MPW tool, this is entirely controlled by the linking step.
  105. It requires system 7 and CFM, which is always the case for PowerPC.
  106. If a m68k version would be implemented, it would save a lot
  107. of efforts if it also uses CFM. This System.pp should, with
  108. minor modifications, probably work with m68k.
  109. Initial working directory is the directory of the application,
  110. or for an MPWTool, the working directory as set by the
  111. Directory command in MPW.
  112. Note about working directory. There is a facility in MacOS which
  113. manages a working directory for an application, initially set to
  114. the applications directory, or for an MPWTool, the tool's directory.
  115. However, this requires the application to have a unique application
  116. signature (creator code), to distinguish its working directory
  117. from working directories of other applications. Due to the fact
  118. that casual applications are anonymous in this sense (without an
  119. application signature), this facility will not work. Also, this
  120. working directory facility is not present in Carbon. Hence we
  121. will manage a working directory by our self.
  122. Deviations
  123. ==========
  124. In current implementation, working directory is stored as
  125. directory id. This means there is a possibility the user moves the
  126. working directory or a parent to it, while the application uses it.
  127. Then the path to the wd suddenly changes. This is AFAIK not in
  128. accordance with other OS's. Although this is a minor caveat,
  129. it is mentioned here. To overcome this the wd could be stored
  130. as a path instead, but this imposes translations from fullpath
  131. to directory ID each time the filesystem is accessed.
  132. The initial working directory for an MPWTool, as considered by
  133. FPC, is different from the MacOS working directory facility,
  134. see above.
  135. Possible improvements:
  136. =====================
  137. Perhaps handle readonly filesystems, as in sysunix.inc
  138. }
  139. {******** include system independent routines **********}
  140. {$I system.inc}
  141. {*********************** MacOS API *********************}
  142. {This implementation uses StdCLib: }
  143. {$define MACOS_USE_STDCLIB}
  144. {Some MacOS API routines and StdCLib included for internal use:}
  145. {$I macostp.inc}
  146. {Note, because the System unit is the most low level, it should not
  147. depend on any other units, and thus the macos api must be accessed
  148. as an include file and not a unit.}
  149. {The reason StdCLib is used is that it can easily be connected
  150. to either SIOW or, in case of MPWTOOL, to MPW }
  151. {If the Apples Universal Interfaces are used, the qd variable is required
  152. to be allocated somewhere, so we do it here for the convenience to the user.}
  153. var
  154. qd: QDGlobals; cvar;
  155. {$ifdef MACOS_USE_STDCLIB}
  156. {************** API to StdCLib in MacOS ***************}
  157. {The reason StdCLib is used is that it can easily be connected
  158. to either SIOW or, in case of MPWTOOL, to MPW }
  159. {$endif}
  160. {*********************** Macutils *********************}
  161. {And also include the same utilities as in the macutils.pp unit.}
  162. var
  163. {emulated working directory}
  164. workingDirectorySpec: FSSpec; cvar;
  165. {Also declared in macutils.pp as external. Declared here to be available
  166. to macutils.inc and below in this file.}
  167. {$I macutils.inc}
  168. {******************************************************}
  169. function GetAppFileLocation (var spec: FSSpec): Boolean;
  170. {Requires >= System 7}
  171. var
  172. PSN: ProcessSerialNumber;
  173. info: ProcessInfoRec;
  174. appFileRefNum: Integer;
  175. appName: Str255;
  176. dummy: Mac_Handle;
  177. begin
  178. begin
  179. PSN.highLongOfPSN := 0;
  180. PSN.lowLongOfPSN := kCurrentProcess;
  181. info.processInfoLength := SizeOf(info);
  182. info.processName := nil;
  183. info.processAppSpec := @spec;
  184. if GetProcessInformation(PSN, info) = noErr then
  185. begin
  186. spec.name := '';
  187. GetAppFileLocation := true;
  188. end
  189. else
  190. GetAppFileLocation := false;
  191. end
  192. end;
  193. Procedure Errno2InOutRes;
  194. {
  195. Convert ErrNo error to the correct InOutRes value.
  196. It seems that some of the errno is, in macos,
  197. used for other purposes than its original definition.
  198. }
  199. begin
  200. if errno = 0 then { Else it will go through all the cases }
  201. exit;
  202. case Errno of
  203. Sys_ENFILE,
  204. Sys_EMFILE : Inoutres:=4;
  205. Sys_ENOENT : Inoutres:=2;
  206. Sys_EBADF : Inoutres:=6;
  207. Sys_ENOMEM,
  208. Sys_EFAULT : Inoutres:=217; //TODO Exchange to something better
  209. Sys_EINVAL : Inoutres:=218; //TODO RTE 218 doesn't exist
  210. Sys_EAGAIN,
  211. Sys_ENOSPC : Inoutres:=101;
  212. Sys_ENOTDIR : Inoutres:=3;
  213. Sys_EPERM,
  214. Sys_EROFS,
  215. Sys_EEXIST,
  216. Sys_EISDIR,
  217. Sys_EINTR, //Happens when attempt to rename a file fails
  218. Sys_EBUSY, //Happens when attempt to remove a locked file
  219. Sys_EACCES,
  220. Sys_EMLINK : Inoutres:=5; //Happens when attempt to remove open file
  221. Sys_ENXIO : InOutRes:=152;
  222. Sys_ESPIPE : InOutRes:=156; //Illegal seek
  223. else
  224. InOutRes := Integer(errno);//TODO Exchange to something better
  225. end;
  226. errno:=0;
  227. end;
  228. Procedure OSErr2InOutRes(err: OSErr);
  229. begin
  230. InOutRes:= MacOSErr2RTEerr(err);
  231. end;
  232. function FSpLocationFromFullPath(fullPathLength: Integer;
  233. fullPath: Mac_Ptr; var spec: FSSpec ):OSErr;
  234. var
  235. alias: AliasHandle;
  236. res: OSErr;
  237. wasChanged: Boolean;
  238. nullString: Str32;
  239. begin
  240. nullString:= '';
  241. res:= NewAliasMinimalFromFullPath(fullPathLength,
  242. fullPath, nullString, nullString, alias);
  243. if res = noErr then
  244. begin
  245. res:= ResolveAlias(nil, alias, spec, wasChanged);
  246. DisposeHandle(Mac_Handle(alias));
  247. end;
  248. FSpLocationFromFullPath:= res;
  249. end;
  250. {*****************************************************************************
  251. MacOS specific functions
  252. *****************************************************************************}
  253. var
  254. defaultCreator: OSType = $4D505320; {'MPS ' MPW Shell}
  255. //defaultCreator: OSType = $74747874; {'ttxt' Simple Text}
  256. defaultFileType: OSType = $54455854; {'TEXT'}
  257. procedure Yield;
  258. begin
  259. if StandAlone = 0 then
  260. SpinCursor(1);
  261. end;
  262. procedure SetDefaultMacOSFiletype(ftype: ShortString);
  263. begin
  264. if Length(ftype) = 4 then
  265. defaultFileType:= PLongWord(@ftype[1])^;
  266. end;
  267. procedure SetDefaultMacOSCreator(creator: ShortString);
  268. begin
  269. if Length(creator) = 4 then
  270. defaultCreator:= PLongWord(@creator[1])^;
  271. end;
  272. {*****************************************************************************
  273. ParamStr/Randomize
  274. *****************************************************************************}
  275. { number of args }
  276. function paramcount : longint;
  277. begin
  278. paramcount := argc - 1;
  279. //paramcount:=0;
  280. end;
  281. { argument number l }
  282. function paramstr(l : longint) : string;
  283. begin
  284. if (l>=0) and (l+1<=argc) then
  285. paramstr:=strpas(argv[l])
  286. else
  287. paramstr:='';
  288. end;
  289. { set randseed to a new pseudo random value }
  290. procedure randomize;
  291. begin
  292. randseed:= Cardinal(TickCount);
  293. end;
  294. {*****************************************************************************
  295. OS Memory allocation / deallocation
  296. ****************************************************************************}
  297. { function to allocate size bytes more for the program }
  298. { must return the first address of new data space or nil if failed }
  299. function SysOSAlloc(size: ptrint): pointer;
  300. begin
  301. result := NewPtr(size);
  302. end;
  303. {$define HAS_SYSOSFREE}
  304. procedure SysOSFree(p: pointer; size: ptrint);
  305. begin
  306. DisposePtr(p);
  307. end;
  308. { include standard heap management }
  309. {$I heap.inc}
  310. {*****************************************************************************
  311. Low Level File Routines
  312. ****************************************************************************}
  313. function do_isdevice(handle:longint):boolean;
  314. begin
  315. do_isdevice:=false;
  316. end;
  317. { close a file from the handle value }
  318. procedure do_close(h : longint);
  319. var
  320. err: OSErr;
  321. {No error handling, according to the other targets, which seems reasonable,
  322. because close might be used to clean up after an error.}
  323. begin
  324. {$ifdef MACOS_USE_STDCLIB}
  325. c_close(h);
  326. // Errno2InOutRes;
  327. {$else}
  328. err:= FSClose(h);
  329. // OSErr2InOutRes(err);
  330. {$endif}
  331. end;
  332. procedure do_erase(p : pchar);
  333. var
  334. spec: FSSpec;
  335. err: OSErr;
  336. res: Integer;
  337. begin
  338. res:= PathArgToFSSpec(p, spec);
  339. if (res = 0) then
  340. begin
  341. if not IsDirectory(spec) then
  342. begin
  343. err:= FSpDelete(spec);
  344. OSErr2InOutRes(err);
  345. end
  346. else
  347. InOutRes:= 2;
  348. end
  349. else
  350. InOutRes:=res;
  351. end;
  352. procedure do_rename(p1,p2 : pchar);
  353. var
  354. s1,s2: AnsiString;
  355. begin
  356. {$ifdef MACOS_USE_STDCLIB}
  357. InOutRes:= PathArgToFullPath(p1, s1);
  358. if InOutRes <> 0 then
  359. exit;
  360. InOutRes:= PathArgToFullPath(p2, s2);
  361. if InOutRes <> 0 then
  362. exit;
  363. c_rename(PChar(s1),PChar(s2));
  364. Errno2InoutRes;
  365. {$else}
  366. InOutRes:=1;
  367. {$endif}
  368. end;
  369. function do_write(h:longint;addr:pointer;len : longint) : longint;
  370. begin
  371. {$ifdef MACOS_USE_STDCLIB}
  372. do_write:= c_write(h, addr, len);
  373. Errno2InoutRes;
  374. {$else}
  375. InOutRes:=1;
  376. if FSWrite(h, len, Mac_Ptr(addr)) = noErr then
  377. InOutRes:=0;
  378. do_write:= len;
  379. {$endif}
  380. end;
  381. function do_read(h:longint;addr:pointer;len : longint) : longint;
  382. var
  383. i: Longint;
  384. begin
  385. {$ifdef MACOS_USE_STDCLIB}
  386. len:= c_read(h, addr, len);
  387. Errno2InoutRes;
  388. do_read:= len;
  389. {$else}
  390. InOutRes:=1;
  391. if FSread(h, len, Mac_Ptr(addr)) = noErr then
  392. InOutRes:=0;
  393. do_read:= len;
  394. {$endif}
  395. end;
  396. function do_filepos(handle : longint) : longint;
  397. var
  398. pos: Longint;
  399. begin
  400. {$ifdef MACOS_USE_STDCLIB}
  401. {This returns the filepos without moving it.}
  402. do_filepos := lseek(handle, 0, SEEK_CUR);
  403. Errno2InoutRes;
  404. {$else}
  405. InOutRes:=1;
  406. if GetFPos(handle, pos) = noErr then
  407. InOutRes:=0;
  408. do_filepos:= pos;
  409. {$endif}
  410. end;
  411. procedure do_seek(handle,pos : longint);
  412. begin
  413. {$ifdef MACOS_USE_STDCLIB}
  414. lseek(handle, pos, SEEK_SET);
  415. Errno2InoutRes;
  416. {$else}
  417. InOutRes:=1;
  418. if SetFPos(handle, fsFromStart, pos) = noErr then
  419. InOutRes:=0;
  420. {$endif}
  421. end;
  422. function do_seekend(handle:longint):longint;
  423. begin
  424. {$ifdef MACOS_USE_STDCLIB}
  425. do_seekend:= lseek(handle, 0, SEEK_END);
  426. Errno2InoutRes;
  427. {$else}
  428. InOutRes:=1;
  429. if SetFPos(handle, fsFromLEOF, 0) = noErr then
  430. InOutRes:=0;
  431. {TODO Resulting file position is to be returned.}
  432. {$endif}
  433. end;
  434. function do_filesize(handle : longint) : longint;
  435. var
  436. aktfilepos: Longint;
  437. begin
  438. {$ifdef MACOS_USE_STDCLIB}
  439. aktfilepos:= lseek(handle, 0, SEEK_CUR);
  440. if errno = 0 then
  441. begin
  442. do_filesize := lseek(handle, 0, SEEK_END);
  443. Errno2InOutRes; {Report the error from this operation.}
  444. lseek(handle, aktfilepos, SEEK_SET); {Always try to move back,
  445. even in presence of error.}
  446. end
  447. else
  448. Errno2InOutRes;
  449. {$else}
  450. InOutRes:=1;
  451. if GetEOF(handle, pos) = noErr then
  452. InOutRes:=0;
  453. do_filesize:= pos;
  454. {$endif}
  455. end;
  456. { truncate at a given position }
  457. procedure do_truncate (handle,pos:longint);
  458. begin
  459. {$ifdef MACOS_USE_STDCLIB}
  460. ioctl(handle, FIOSETEOF, pointer(pos));
  461. Errno2InoutRes;
  462. {$else}
  463. InOutRes:=1;
  464. do_seek(handle,pos); //TODO: Is this needed (Does the user anticipate the filemarker is at the end?)
  465. if SetEOF(handle, pos) = noErr then
  466. InOutRes:=0;
  467. {$endif}
  468. end;
  469. procedure do_open(var f;p:pchar;flags:longint);
  470. {
  471. filerec and textrec have both handle and mode as the first items so
  472. they could use the same routine for opening/creating.
  473. when (flags and $100) the file will be append
  474. when (flags and $1000) the file will be truncate/rewritten
  475. when (flags and $10000) there is no check for close (needed for textfiles)
  476. }
  477. var
  478. scriptTag: ScriptCode;
  479. refNum: Integer;
  480. err: OSErr;
  481. res: Integer;
  482. spec: FSSpec;
  483. fh: Longint;
  484. oflags : longint;
  485. fullPath: AnsiString;
  486. finderInfo: FInfo;
  487. begin
  488. // AllowSlash(p);
  489. { close first if opened }
  490. if ((flags and $10000)=0) then
  491. begin
  492. case filerec(f).mode of
  493. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  494. fmclosed : ;
  495. else
  496. begin
  497. {not assigned}
  498. inoutres:=102;
  499. exit;
  500. end;
  501. end;
  502. end;
  503. { reset file handle }
  504. filerec(f).handle:=UnusedHandle;
  505. {$ifdef MACOS_USE_STDCLIB}
  506. { We do the conversion of filemodes here, concentrated on 1 place }
  507. case (flags and 3) of
  508. 0 : begin
  509. oflags :=O_RDONLY;
  510. filerec(f).mode:=fminput;
  511. end;
  512. 1 : begin
  513. oflags :=O_WRONLY;
  514. filerec(f).mode:=fmoutput;
  515. end;
  516. 2 : begin
  517. oflags :=O_RDWR;
  518. filerec(f).mode:=fminout;
  519. end;
  520. end;
  521. if (flags and $1000)=$1000 then
  522. oflags:=oflags or (O_CREAT or O_TRUNC)
  523. else if (flags and $100)=$100 then
  524. oflags:=oflags or (O_APPEND);
  525. { empty name is special }
  526. if p[0]=#0 then
  527. begin
  528. case FileRec(f).mode of
  529. fminput :
  530. FileRec(f).Handle:=StdInputHandle;
  531. fminout, { this is set by rewrite }
  532. fmoutput :
  533. FileRec(f).Handle:=StdOutputHandle;
  534. fmappend :
  535. begin
  536. FileRec(f).Handle:=StdOutputHandle;
  537. FileRec(f).mode:=fmoutput; {fool fmappend}
  538. end;
  539. end;
  540. exit;
  541. end
  542. else
  543. begin
  544. InOutRes:= PathArgToFSSpec(p, spec);
  545. if (InOutRes = 0) or (InOutRes = 2) then
  546. begin
  547. err:= FSpGetFullPath(spec, fullPath, false);
  548. InOutRes:= MacOSErr2RTEerr(err);
  549. end;
  550. if InOutRes <> 0 then
  551. exit;
  552. p:= PChar(fullPath);
  553. end;
  554. fh:= c_open(p, oflags);
  555. if (fh = -1) and (errno = Sys_EROFS) and ((oflags and O_RDWR)<>0) then
  556. begin
  557. oflags:=oflags and not(O_RDWR);
  558. fh:= c_open(p, oflags);
  559. end;
  560. Errno2InOutRes;
  561. if fh <> -1 then
  562. begin
  563. if FileRec(f).mode in [fmoutput, fminout, fmappend] then
  564. begin
  565. {Change of filetype and creator is always done when a file is opened
  566. for some kind of writing. This ensures overwritten Darwin files will
  567. get apropriate filetype. It must be done after file is opened,
  568. in the case the file did not previously exist.}
  569. FSpGetFInfo(spec, finderInfo);
  570. finderInfo.fdType:= defaultFileType;
  571. finderInfo.fdCreator:= defaultCreator;
  572. FSpSetFInfo(spec, finderInfo);
  573. end;
  574. filerec(f).handle:= fh;
  575. end
  576. else
  577. filerec(f).handle:= UnusedHandle;
  578. {$else}
  579. InOutRes:=1;
  580. { reset file handle }
  581. filerec(f).handle:=UnusedHandle;
  582. res:= FSpLocationFromFullPath(StrLen(p), p, spec);
  583. if (res = noErr) or (res = fnfErr) then
  584. begin
  585. if FSpCreate(spec, defaultCreator, defaultFileType, smSystemScript) = noErr then
  586. ;
  587. if FSpOpenDF(spec, fsCurPerm, refNum) = noErr then
  588. begin
  589. filerec(f).handle:= refNum;
  590. InOutRes:=0;
  591. end;
  592. end;
  593. if (filerec(f).handle=UnusedHandle) then
  594. begin
  595. //errno:=GetLastError;
  596. //Errno2InoutRes;
  597. end;
  598. {$endif}
  599. end;
  600. {*****************************************************************************
  601. UnTyped File Handling
  602. *****************************************************************************}
  603. {$i file.inc}
  604. {*****************************************************************************
  605. Typed File Handling
  606. *****************************************************************************}
  607. {$i typefile.inc}
  608. {*****************************************************************************
  609. Text File Handling
  610. *****************************************************************************}
  611. { #26 is not end of a file in MacOS ! }
  612. {$i text.inc}
  613. {*****************************************************************************
  614. Directory Handling
  615. *****************************************************************************}
  616. procedure mkdir(const s:string);[IOCheck];
  617. var
  618. spec: FSSpec;
  619. createdDirID: Longint;
  620. err: OSErr;
  621. res: Integer;
  622. begin
  623. If (s='') or (InOutRes <> 0) then
  624. exit;
  625. res:= PathArgToFSSpec(s, spec);
  626. if (res = 0) or (res = 2) then
  627. begin
  628. err:= FSpDirCreate(spec, smSystemScript, createdDirID);
  629. OSErr2InOutRes(err);
  630. end
  631. else
  632. InOutRes:=res;
  633. end;
  634. procedure rmdir(const s:string);[IOCheck];
  635. var
  636. spec: FSSpec;
  637. err: OSErr;
  638. res: Integer;
  639. begin
  640. If (s='') or (InOutRes <> 0) then
  641. exit;
  642. res:= PathArgToFSSpec(s, spec);
  643. if (res = 0) then
  644. begin
  645. if IsDirectory(spec) then
  646. begin
  647. err:= FSpDelete(spec);
  648. OSErr2InOutRes(err);
  649. end
  650. else
  651. InOutRes:= 20;
  652. end
  653. else
  654. InOutRes:=res;
  655. end;
  656. procedure chdir(const s:string);[IOCheck];
  657. var
  658. spec, newDirSpec: FSSpec;
  659. err: OSErr;
  660. res: Integer;
  661. begin
  662. if (s='') or (InOutRes <> 0) then
  663. exit;
  664. res:= PathArgToFSSpec(s, spec);
  665. if (res = 0) or (res = 2) then
  666. begin
  667. { The fictive file x is appended to the directory name to make
  668. FSMakeFSSpec return a FSSpec to a file in the directory.
  669. Then by clearing the name, the FSSpec then
  670. points to the directory. It doesn't matter whether x exists or not.}
  671. err:= FSMakeFSSpec (spec.vRefNum, spec.parID, ':'+spec.name+':x', newDirSpec);
  672. if (err = noErr) or (err = fnfErr) then
  673. begin
  674. workingDirectorySpec:= newDirSpec;
  675. workingDirectorySpec.name:='';
  676. InOutRes:= 0;
  677. end
  678. else
  679. begin
  680. {E g if the directory doesn't exist.}
  681. OSErr2InOutRes(err);
  682. end;
  683. end
  684. else
  685. InOutRes:=res;
  686. end;
  687. procedure getDir (DriveNr: byte; var Dir: ShortString);
  688. var
  689. fullPath: AnsiString;
  690. pathHandleSize: Longint;
  691. begin
  692. if FSpGetFullPath(workingDirectorySpec, fullPath, false) <> noErr then
  693. Halt(3); {exit code 3 according to MPW}
  694. if Length(fullPath) <= 255 then {because dir is ShortString}
  695. InOutRes := 0
  696. else
  697. InOutRes := 1; //TODO Exchange to something better
  698. dir:= fullPath;
  699. end;
  700. {*****************************************************************************
  701. SystemUnit Initialization
  702. *****************************************************************************}
  703. procedure pascalmain; external name 'PASCALMAIN';
  704. {Main entry point in C style, needed to capture program parameters.
  705. For this to work, the system unit must be before the main program
  706. in the linking order.}
  707. procedure main(argcparam: Longint; argvparam: ppchar; envpparam: ppchar); cdecl; [public];
  708. begin
  709. argc:= argcparam;
  710. argv:= argvparam;
  711. envp:= envpparam;
  712. pascalmain; {run the pascal main program}
  713. end;
  714. procedure setup_arguments;
  715. begin
  716. {Nothing needs to be done here.}
  717. end;
  718. procedure setup_environment;
  719. begin
  720. end;
  721. { FindSysFolder returns the (real) vRefNum, and the DirID of the current
  722. system folder. It uses the Folder Manager if present, otherwise it falls
  723. back to SysEnvirons. It returns zero on success, otherwise a standard
  724. system error. }
  725. function FindSysFolder(var foundVRefNum: Integer; var foundDirID: Longint): OSErr;
  726. var
  727. gesResponse: Longint;
  728. envRec: SysEnvRec;
  729. myWDPB: WDPBRec;
  730. volName: String[34];
  731. err: OSErr;
  732. begin
  733. foundVRefNum := 0;
  734. foundDirID := 0;
  735. if macosHasGestalt
  736. and (Gestalt (FourCharCodeToLongword(gestaltFindFolderAttr), gesResponse) = noErr)
  737. and BitIsSet (gesResponse, gestaltFindFolderPresent) then
  738. begin { Does Folder Manager exist? }
  739. err := FindFolder (kOnSystemDisk, FourCharCodeToLongword(kSystemFolderType),
  740. kDontCreateFolder, foundVRefNum, foundDirID);
  741. end
  742. else
  743. begin
  744. { Gestalt can't give us the answer, so we resort to SysEnvirons }
  745. err := SysEnvirons (curSysEnvVers, envRec);
  746. if (err = noErr) then
  747. begin
  748. myWDPB.ioVRefNum := envRec.sysVRefNum;
  749. volName := '';
  750. myWDPB.ioNamePtr := @volName;
  751. myWDPB.ioWDIndex := 0;
  752. myWDPB.ioWDProcID := 0;
  753. err := PBGetWDInfoSync (@myWDPB);
  754. if (err = noErr) then
  755. begin
  756. foundVRefNum := myWDPB.ioWDVRefNum;
  757. foundDirID := myWDPB.ioWDDirID;
  758. end;
  759. end;
  760. end;
  761. FindSysFolder:= err;
  762. end;
  763. procedure InvestigateSystem;
  764. {$IFDEF CPUM68K}
  765. const
  766. _GestaltDispatch = $A0AD;
  767. _WaitNextEvent = $A860;
  768. _ScriptUtil = $A8B5;
  769. qdOffscreenTrap = $AB1D;
  770. {$ENDIF}
  771. var
  772. err: Integer;
  773. response: Longint;
  774. {$IFDEF CPUM68K}
  775. environs: SysEnvRec;
  776. {$ENDIF}
  777. {Vi rŠknar med att man kšr pŒ minst system 6.0.5. DŒ finns bŒde Gestalt och GDevice med.}
  778. {Enligt Change Histrory Šr MacOS 6.0.5 mera konsistent mellan maskinmodellerna Šn fšregŒende system}
  779. begin
  780. {$IFDEF CPUM68K}
  781. macosHasGestalt := TrapAvailable(_GestaltDispatch);
  782. {$ELSE}
  783. macosHasGestalt := true; {There is always Gestalt on PowerPC}
  784. {$ENDIF}
  785. if not macosHasGestalt then (* If we don't have Gestalt, then we can't have any System 7 features *)
  786. begin
  787. {$IFDEF CPUM68K}
  788. { Detta kan endast gŠlla pŒ en 68K maskin.}
  789. macosHasScriptMgr := TrapAvailable(_ScriptUtil);
  790. macosNrOfScriptsInstalled := 1; (* assume only Roman script, to start with *)
  791. err := SysEnvirons(1, environs);
  792. if err = noErr then
  793. begin
  794. if environs.machineType < 0 then { gammalt ROM}
  795. macosHasWaitNextEvent := FALSE
  796. else
  797. macosHasWaitNextEvent := TrapAvailable(_WaitNextEvent);
  798. macosHasColorQD := environs.hasColorQD;
  799. macosHasFPU := environs.hasFPU;
  800. macosSystemVersion := environs.systemVersion;
  801. end
  802. else
  803. begin
  804. macosHasWaitNextEvent := FALSE;
  805. macosHasColorQD := FALSE;
  806. macosHasFPU := FALSE;
  807. macosSystemVersion := 0;
  808. end;
  809. macosHasSysDebugger := (LongintPtr(MacJmp)^ <> 0);
  810. macosHasCFM := false;
  811. macosHasAppleEvents := false;
  812. macosHasAliasMgr := false;
  813. macosHasFSSpec := false;
  814. macosHasFindFolder := false;
  815. macosHasAppearance := false;
  816. macosHasAppearance101 := false;
  817. macosHasAppearance11 := false;
  818. {$IFDEF THINK_PASCAL}
  819. if (macosHasScriptMgr) then
  820. macosNrOfScriptsInstalled := GetEnvirons(smEnabled);
  821. {$ELSE}
  822. if (macosHasScriptMgr) then
  823. macosNrOfScriptsInstalled := GetScriptManagerVariable(smEnabled); {Gamla rutinnamnet var GetEnvirons.}
  824. {$ENDIF}
  825. {$ENDIF}
  826. end
  827. else
  828. begin
  829. macosHasScriptMgr := Gestalt(FourCharCodeToLongword(gestaltScriptMgrVersion), response) = noErr; {Fšr att ta reda pŒ om script mgr finns.}
  830. macosNrOfScriptsInstalled := 1; (* assume only Roman script, to start with *)
  831. macosHasWaitNextEvent := true;
  832. if Gestalt(FourCharCodeToLongword(gestaltSystemVersion), response) = noErr then
  833. macosSystemVersion := response
  834. else
  835. macosSystemVersion := 0; {Borde inte kunna hŠnda.}
  836. if Gestalt(FourCharCodeToLongword(gestaltOSAttr), response) = noErr then
  837. macosHasSysDebugger := BitIsSet(response, gestaltSysDebuggerSupport)
  838. else
  839. macosHasSysDebugger := false;
  840. if Gestalt(FourCharCodeToLongword(gestaltQuickdrawVersion), response) = noErr then
  841. macosHasColorQD := (response >= $0100)
  842. else
  843. macosHasColorQD := false;
  844. if Gestalt(FourCharCodeToLongword(gestaltFPUType), response) = noErr then
  845. macosHasFPU := (response <> gestaltNoFPU)
  846. else
  847. macosHasFPU := false;
  848. if Gestalt(FourCharCodeToLongword(gestaltCFMAttr), response) = noErr then
  849. macosHasCFM := BitIsSet(response, gestaltCFMPresent)
  850. else
  851. macosHasCFM := false;
  852. macosHasAppleEvents := Gestalt(FourCharCodeToLongword(gestaltAppleEventsAttr), response) = noErr;
  853. macosHasAliasMgr := Gestalt(FourCharCodeToLongword(gestaltAliasMgrAttr), response) = noErr;
  854. if Gestalt(FourCharCodeToLongword(gestaltFSAttr), response) = noErr then
  855. macosHasFSSpec := BitIsSet(response, gestaltHasFSSpecCalls)
  856. else
  857. macosHasFSSpec := false;
  858. macosHasFindFolder := Gestalt(FourCharCodeToLongword(gestaltFindFolderAttr), response) = noErr;
  859. if macosHasScriptMgr then
  860. begin
  861. err := Gestalt(FourCharCodeToLongword(gestaltScriptCount), response);
  862. if (err = noErr) then
  863. macosNrOfScriptsInstalled := Integer(response);
  864. end;
  865. if (Gestalt(FourCharCodeToLongword(gestaltAppearanceAttr), response) = noErr) then
  866. begin
  867. macosHasAppearance := BitIsSet(response, gestaltAppearanceExists);
  868. if Gestalt(FourCharCodeToLongword(gestaltAppearanceVersion), response) = noErr then
  869. begin
  870. macosHasAppearance101 := (response >= $101);
  871. macosHasAppearance11 := (response >= $110);
  872. end
  873. end
  874. else
  875. begin
  876. macosHasAppearance := false;
  877. macosHasAppearance101 := false;
  878. macosHasAppearance11 := false;
  879. end;
  880. end;
  881. end;
  882. {*****************************************************************************
  883. System Dependent Exit code
  884. *****************************************************************************}
  885. Procedure system_exit;
  886. var
  887. s: ShortString;
  888. begin
  889. if StandAlone <> 0 then
  890. if exitcode <> 0 then
  891. begin
  892. Str(exitcode,s);
  893. if IsConsole then
  894. Writeln( '### Program exited with exit code ' + s)
  895. else if macosHasSysDebugger then
  896. DebugStr('A possible error occured, exit code: ' + s + '. Type "g" and return to continue.')
  897. else
  898. {Be quiet}
  899. end;
  900. {$ifndef MACOS_USE_STDCLIB}
  901. if StandAlone <> 0 then
  902. ExitToShell;
  903. {$else}
  904. c_exit(exitcode); {exitcode is only utilized by an MPW tool}
  905. {$endif}
  906. end;
  907. procedure SysInitStdIO;
  908. begin
  909. { Setup stdin, stdout and stderr }
  910. {$ifdef MACOS_USE_STDCLIB}
  911. OpenStdIO(Input,fmInput,StdInputHandle);
  912. OpenStdIO(Output,fmOutput,StdOutputHandle);
  913. OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
  914. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  915. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  916. {$endif }
  917. end;
  918. function GetProcessID: SizeUInt;
  919. begin
  920. GetProcessID := 1;
  921. {$WARNING To be implemented - using GetProcessInformation???}
  922. end;
  923. var
  924. resHdl: Mac_Handle;
  925. isFolder, hadAlias, leafIsAlias: Boolean;
  926. dirStr: string[2];
  927. err: OSErr;
  928. dummySysFolderDirID: Longint;
  929. begin
  930. InvestigateSystem; {Must be first}
  931. {Check requred features for system.pp to work.}
  932. if not macosHasFSSpec then
  933. Halt(3); //exit code 3 according to MPW
  934. if FindSysFolder(macosBootVolumeVRefNum, dummySysFolderDirID) <> noErr then
  935. Halt(3); //exit code 3 according to MPW
  936. if GetVolumeName(macosBootVolumeVRefNum, macosBootVolumeName) <> noErr then
  937. Halt(3); //exit code 3 according to MPW
  938. { To be set if this is a GUI or console application }
  939. if StandAlone = 0 then
  940. IsConsole := true {Its an MPW tool}
  941. else
  942. begin
  943. resHdl:= Get1Resource(FourCharCodeToLongword('siow'),0);
  944. IsConsole := (resHdl <> nil); {A SIOW app is also a console}
  945. ReleaseResource(resHdl);
  946. end;
  947. { To be set if this is a library and not a program }
  948. IsLibrary := FALSE;
  949. StackLength := InitialStkLen;
  950. StackBottom := SPtr - StackLength;
  951. { Setup working directory }
  952. if StandAlone <> 0 then
  953. begin
  954. if not GetAppFileLocation(workingDirectorySpec) then
  955. Halt(3); //exit code 3 according to MPW
  956. end
  957. else
  958. begin
  959. { The fictive file x is used to make
  960. FSMakeFSSpec return a FSSpec to a file in the directory.
  961. Then by clearing the name, the FSSpec then
  962. points to the directory. It doesn't matter whether x exists or not.}
  963. dirStr:= ':x';
  964. err:= ResolveFolderAliases(0, 0, @dirStr, true,
  965. workingDirectorySpec, isFolder, hadAlias, leafIsAlias);
  966. workingDirectorySpec.name:='';
  967. if (err <> noErr) and (err <> fnfErr) then
  968. Halt(3); //exit code 3 according to MPW
  969. end;
  970. { Setup heap }
  971. if StandAlone <> 0 then
  972. MaxApplZone;
  973. InitHeap;
  974. SysInitExceptions;
  975. SysInitStdIO;
  976. { Setup environment and arguments }
  977. Setup_Environment;
  978. setup_arguments;
  979. { Reset IO Error }
  980. InOutRes:=0;
  981. errno:=0;
  982. (* This should be changed to a real value during *)
  983. (* thread driver initialization if appropriate. *)
  984. ThreadID := 1;
  985. {$ifdef HASVARIANT}
  986. initvariantmanager;
  987. {$endif HASVARIANT}
  988. {$ifdef HASWIDESTRING}
  989. initwidestringmanager;
  990. {$endif HASWIDESTRING}
  991. if StandAlone = 0 then
  992. begin
  993. InitGraf(@qd.thePort);
  994. SetFScaleDisable(true);
  995. InitCursorCtl(nil);
  996. end;
  997. end.
  998. {
  999. $Log$
  1000. Revision 1.28 2005-02-01 20:22:49 florian
  1001. * improved widestring infrastructure manager
  1002. Revision 1.27 2005/01/24 18:51:23 olle
  1003. * filetype/filecreator changed after the file is opened, in case the file did not previously exist
  1004. Revision 1.26 2004/12/05 14:36:37 hajny
  1005. + GetProcessID added
  1006. Revision 1.25 2004/11/04 09:32:31 peter
  1007. ErrOutput added
  1008. Revision 1.24 2004/10/25 15:38:59 peter
  1009. * compiler defined HEAP and HEAPSIZE removed
  1010. Revision 1.23 2004/10/19 19:56:59 olle
  1011. * Interface to StdLibC moved from system to macostp
  1012. Revision 1.22 2004/09/30 19:58:42 olle
  1013. + Added SetDefaultMacOS[Filetype|Creator]
  1014. * Files written to by fpc rtl now always will get decent filetype/creator
  1015. * Adapted to use FSpGetFullPath
  1016. Revision 1.21 2004/09/12 19:51:02 olle
  1017. + InitGraf called for MPW tool, which make strange bug disappear.
  1018. * bugfix initial wd for MPW tool
  1019. + Added SysInitExceptions
  1020. Revision 1.20 2004/09/03 19:26:08 olle
  1021. + added maxExitCode to all System.pp
  1022. * constrained error code to be below maxExitCode in RunError et. al.
  1023. Revision 1.19 2004/08/20 10:18:15 olle
  1024. + added Yield routine
  1025. Revision 1.18 2004/07/14 23:34:07 olle
  1026. + added qd, the "QuickDraw globals"
  1027. Revision 1.17 2004/06/21 19:23:34 olle
  1028. + Variables describing misc OS features added
  1029. + Detection of GUI app
  1030. * Working directory for APPTYPE TOOL correct now
  1031. + Exit code <> 0 written to, console for console apps, to system debugger (if installed) for GUI apps.
  1032. * Misc fixes
  1033. Revision 1.16 2004/06/17 16:16:13 peter
  1034. * New heapmanager that releases memory back to the OS, donated
  1035. by Micha Nelissen
  1036. Revision 1.15 2004/05/11 18:05:41 olle
  1037. + added call to MaxApplZone to have the whole MacOS heap available
  1038. Revision 1.14 2004/04/29 11:27:36 olle
  1039. * do_read/do_write addr arg changed to pointer
  1040. * misc internal changes
  1041. Revision 1.13 2004/02/04 15:17:16 olle
  1042. * internal changes
  1043. Revision 1.12 2004/01/20 23:11:20 hajny
  1044. * ExecuteProcess fixes, ProcessID and ThreadID added
  1045. Revision 1.11 2004/01/04 21:06:43 jonas
  1046. * make the C-main public
  1047. Revision 1.10 2003/10/29 22:34:52 olle
  1048. + handles program parameters for MPW
  1049. + program start stub
  1050. * improved working directory handling
  1051. * minor changes
  1052. + some documentation
  1053. Revision 1.9 2003/10/17 23:44:30 olle
  1054. + working direcory emulated
  1055. + implemented directory handling procs
  1056. + all proc which take a path param, now resolve it relative wd
  1057. Revision 1.8 2003/10/16 15:43:13 peter
  1058. * THandle is platform dependent
  1059. Revision 1.7 2003/09/27 11:52:35 peter
  1060. * sbrk returns pointer
  1061. Revision 1.6 2003/09/12 12:45:15 olle
  1062. + filehandling complete
  1063. + heaphandling complete
  1064. + support for random
  1065. * filehandling now uses filedecriptors in StdCLib
  1066. * other minor changes
  1067. - removed DEFINE MAC_SYS_RUNNABLE
  1068. Revision 1.5 2003/01/13 17:18:55 olle
  1069. + added support for rudimentary file handling
  1070. Revision 1.4 2002/11/28 10:58:02 olle
  1071. + added support for rudimentary heap
  1072. Revision 1.3 2002/10/23 15:29:09 olle
  1073. + added switch MAC_SYS_RUNABLE
  1074. + added include of system.h etc
  1075. + added standard globals
  1076. + added dummy hook procedures
  1077. Revision 1.2 2002/10/10 19:44:05 florian
  1078. * changes from Olle to compile/link a simple program
  1079. Revision 1.1 2002/10/02 21:34:31 florian
  1080. * first dummy implementation
  1081. }