12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184 |
- {
- $Id$
- This file is part of the Free Pascal run time library.
- Copyright (c) 2002-2003 by Olle Raab
- FreePascal system unit for MacOS.
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit System;
- interface
- { include system-independent routine headers }
- {$I systemh.inc}
- {Platform specific information}
- type
- {$ifdef CPU64}
- THandle = Int64;
- {$else CPU64}
- THandle = Longint;
- {$endif CPU64}
- const
- LineEnding = #13;
- LFNSupport = true;
- DirectorySeparator = ':';
- DriveSeparator = ':';
- PathSeparator = ','; // Is used in MPW and OzTeX
- FileNameCaseSensitive = false;
- { include heap support headers }
- {$I heaph.inc}
- const
- { Default filehandles }
- UnusedHandle : Longint = -1;
- StdInputHandle : Longint = 0;
- StdOutputHandle : Longint = 1;
- StdErrorHandle : Longint = 2;
- sLineBreak = LineEnding;
- DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCR;
- var
- argc : longint;
- argv : ppchar;
- envp : ppchar;
- {
- MacOS paths
- ===========
- MacOS directory separator is a colon ":" which is the only character not
- allowed in filenames.
- A path containing no colon or which begins with a colon is a partial path.
- E g ":kalle:petter" ":kalle" "kalle"
- All other paths are full (absolute) paths. E g "HD:kalle:" "HD:"
- When generating paths, one is safe is one ensures that all partial paths
- begins with a colon, and all full paths ends with a colon.
- In full paths the first name (e g HD above) is the name of a mounted volume.
- These names are not unique, because, for instance, two diskettes with the
- same names could be inserted. This means that paths on MacOS is not
- waterproof. In case of equal names the first volume found will do.
- Two colons "::" are the relative path to the parent. Three is to the
- grandparent etc.
- }
- implementation
- {
- About the implementation
- ========================
- A MacOS application is assembled and linked by MPW (Macintosh
- Programmers Workshop), which nowadays is free to use. For info
- and download of MPW and MacOS api, see www.apple.com
- It can be linked to either a standalone application (using SIOW) or
- to an MPW tool, this is entirely controlled by the linking step.
- It requires system 7 and CFM, which is always the case for PowerPC.
- If a m68k version would be implemented, it would save a lot
- of efforts if it also uses CFM. This System.pp should, with
- minor modifications, probably work with m68k.
- Initial working directory is the directory of the application,
- or for an MPWTool, the MPW directory.
- Note about working directory. There is a facility in MacOS which
- manages a working directory for an application, initially set to
- the applictaions directory, or for an MPWTool, the tool's directory.
- However, this requires the application to have a unique application
- signature (creator code), to distinguish its working directory
- from working directories of other applications. Due to the fact
- that casual applications are anonymous in this sense (without an
- application signature), this facility will not work. Hence we
- will manage a working directory by our self.
- Deviations
- ==========
- In current implementation, working directory is stored as
- directory id. This means there is a possibility the user moves the
- working directory or a parent to it, while the application uses it.
- Then the path to the wd suddenly changes. This is AFAIK not in
- accordance with other OS's. Although this is a minor caveat,
- it is mentioned here. To overcome this the wd could be stored
- as a path instead, but this imposes translations from fullpath
- to directory id each time the filesystem is accessed.
- The initial working directory for an MPWTool, as considered by
- FPC, is different from the MacOS working directory facility,
- see above.
- Possible improvements:
- =====================
- TODO: Add check so that working directory cannot be removed. Alt ensure
- the nothing crashes if wd is removed.
- TODO: rmdir and erase does not differentiate between files and directories
- thus removing both of them.
- TODO: Check of the MacOS version (and prescence of CFM) to
- ensure it is a supported version. only needed for m68k.
- }
- {This implementation uses StdCLib, which is included in the MPW.}
- {$define MACOS_USE_STDCLIB}
- {******** include system independent routines **********}
- {$I system.inc}
- {*********************** MacOS API *********************}
- {Below is some MacOS API routines included for internal use.
- Note, because the System unit is the most low level, it should not
- depend on any other units, and thus the macos api must be accessed
- as an include file and not a unit.}
- {$I macostp.inc}
- {$ifdef MACOS_USE_STDCLIB}
- {************** API to StdCLib in MacOS ***************}
- {The reason StdCLib is used is that it can easily be connected
- to either SIOW or, in case of MPWTOOL, to MPW }
- {The prefix C_ or c_ is used where names conflicts with pascal
- keywords and names. Suffix Ptr is added for pointer to a type.}
- type
- size_t = Longint;
- off_t = Longint;
- C_int = Longint;
- C_short = Integer;
- C_long = Longint;
- C_unsigned_int = Cardinal;
- var
- errno: C_int; external name 'errno';
- MacOSErr: C_short; external name 'MacOSErr';
- const
- _IOFBF = $00;
- _IOLBF = $40;
- _IONBF = $04;
- O_RDONLY = $00; // Open for reading only.
- O_WRONLY = $01; // Open for writing only.
- O_RDWR = $02; // Open for reading & writing.
- O_APPEND = $08; // Write to the end of the file.
- O_RSRC = $10; // Open the resource fork.
- O_ALIAS = $20; // Open alias file.
- O_CREAT = $100; // Open or create a file.
- O_TRUNC = $200; // Open and truncate to zero length.
- O_EXCL = $400; // Create file only; fail if exists.
- O_BINARY = $800; // Open as a binary stream.
- O_NRESOLVE = $4000; // Don't resolve any aliases.
- SEEK_SET = 0;
- SEEK_CUR = 1;
- SEEK_END = 2;
- FIOINTERACTIVE = $00006602; // If device is interactive
- FIOBUFSIZE = $00006603; // Return optimal buffer size
- FIOFNAME = $00006604; // Return filename
- FIOREFNUM = $00006605; // Return fs refnum
- FIOSETEOF = $00006606; // Set file length
- TIOFLUSH = $00007408; // discard unread input. arg is ignored
- function c_open(path: PChar; oflag: C_int): C_int; cdecl;
- external 'StdCLib' name 'open';
- function c_close(filedes: C_int): C_int; cdecl;
- external 'StdCLib' name 'close';
- function c_write(filedes: C_int; buf: pointer; nbyte: size_t): size_t; cdecl;
- external 'StdCLib' name 'write';
- function c_read(filedes: C_int; buf: pointer; nbyte: size_t): size_t; cdecl;
- external 'StdCLib' name 'read';
- function lseek(filedes: C_int; offset: off_t; whence: C_int): off_t; cdecl;
- external 'StdCLib' name 'lseek';
- function ioctl(filedes: C_int; cmd: C_unsigned_int; arg: pointer): C_int; cdecl;
- external 'StdCLib' name 'ioctl';
- function remove(filename: PChar): C_int; cdecl;
- external 'StdCLib';
- function c_rename(old, c_new: PChar): C_int; cdecl;
- external 'StdCLib' name 'rename';
- procedure c_exit(status: C_int); cdecl;
- external 'StdCLib' name 'exit';
- {cdecl is actually only needed for m68k}
- var
- {Is set to nonzero for MPWTool, zero otherwise.}
- StandAlone: C_int; external name 'StandAlone';
- CONST
- Sys_EPERM = 1; { No permission match }
- Sys_ENOENT = 2; { No such file or directory }
- Sys_ENORSRC = 3; { Resource not found *}
- Sys_EINTR = 4; { System service interrupted *}
- Sys_EIO = 5; { I/O error }
- Sys_ENXIO = 6; { No such device or address }
- Sys_E2BIG = 7; { Insufficient space for return argument * }
- Sys_ENOEXEC = 8; { File not executable * }
- Sys_EBADF = 9; { Bad file number }
- Sys_ECHILD = 10; { No child processes }
- Sys_EAGAIN = 11; { Resource temporarily unavailable * }
- Sys_ENOMEM = 12; { Not enough space * }
- Sys_EACCES = 13; { Permission denied }
- Sys_EFAULT = 14; { Illegal filename * }
- Sys_ENOTBLK = 15; { Block device required }
- Sys_EBUSY = 16; { Device or resource busy }
- Sys_EEXIST = 17; { File exists }
- Sys_EXDEV = 18; { Cross-device link }
- Sys_ENODEV = 19; { No such device }
- Sys_ENOTDIR = 20; { Not a directory }
- Sys_EISDIR = 21; { Is a directory }
- Sys_EINVAL = 22; { Invalid parameter * }
- Sys_ENFILE = 23; { File table overflow }
- Sys_EMFILE = 24; { Too many open files }
- Sys_ENOTTY = 25; { Not a typewriter }
- Sys_ETXTBSY = 26; { Text file busy }
- Sys_EFBIG = 27; { File too large }
- Sys_ENOSPC = 28; { No space left on device }
- Sys_ESPIPE = 29; { Illegal seek }
- Sys_EROFS = 30; { Read-only file system }
- Sys_EMLINK = 31; { Too many links }
- Sys_EPIPE = 32; { Broken pipe }
- Sys_EDOM = 33; { Math argument out of domain of func }
- Sys_ERANGE = 34; { Math result not representable }
- { Note * is slightly different, compared to rtl/sunos/errno.inc}
- {$endif}
- {******************************************************}
- var
- {working directory}
- curDirectorySpec: FSSpec;
- function GetAppFileLocation (var spec: FSSpec): Boolean;
- //Requires >= System 7
- var
- PSN: ProcessSerialNumber;
- info: ProcessInfoRec;
- appFileRefNum: Integer;
- appName: Str255;
- dummy: Mac_Handle;
- begin
- begin
- PSN.highLongOfPSN := 0;
- PSN.lowLongOfPSN := kCurrentProcess;
- info.processInfoLength := SizeOf(info);
- info.processName := nil;
- info.processAppSpec := @spec;
- if GetProcessInformation(PSN, info) = noErr then
- begin
- spec.name := '';
- GetAppFileLocation := true;
- end
- else
- GetAppFileLocation := false;
- end
- end;
- {Gives the path for a given file or directory. If parent is true,
- a path to the directory, where the file or directory is located,
- is returned. Functioning even with System 6}
- function FSpGetFullPath (spec: FSSpec; var fullPathHandle: Mac_Handle;
- parent: Boolean): OSErr;
- var
- res: OSErr;
- pb: CInfoPBRec;
- begin
- fullPathHandle:= NewHandle(0); { Allocate a zero-length handle }
- if fullPathHandle = nil then
- begin
- FSpGetFullPath:= MemError;
- Exit;
- end;
- if spec.parID = fsRtParID then { The object is a volume }
- begin
- if not parent then
- begin
- { Add a colon to make it a full pathname }
- spec.name := Concat(spec.name, ':');
- { We're done }
- Munger(fullPathHandle, 0, nil, 0, @spec.name[1], Length(spec.name));
- res := MemError;
- end
- else
- res := noErr;
- end
- else
- begin
- { The object isn't a volume }
- { Add the object name }
- if not parent then
- Munger(fullPathHandle, 0, nil, 0, @spec.name[1], Length(spec.name));
- { Get the ancestor directory names }
- pb.ioNamePtr := @spec.name;
- pb.ioVRefNum := spec.vRefNum;
- pb.ioDrParID := spec.parID;
- repeat { loop until we have an error or find the root directory }
- begin
- pb.ioFDirIndex := -1;
- pb.ioDrDirID := pb.ioDrParID;
- res := PBGetCatInfoSync(@pb);
- if res = noErr then
- begin
- { Append colon to directory name }
- spec.name := Concat(spec.name, ':');
- { Add directory name to fullPathHandle }
- Munger(fullPathHandle, 0, nil, 0, @spec.name[1], Length(spec.name));
- res := MemError;
- end
- end
- until not ((res = noErr) and (pb.ioDrDirID <> fsRtDirID));
- end;
- if res <> noErr then
- begin
- DisposeHandle(fullPathHandle);
- fullPathHandle:= nil;
- end;
- FSpGetFullPath := res;
- end;
- Procedure Errno2InOutRes;
- {
- Convert ErrNo error to the correct InOutRes value.
- It seems that some of the errno is, in macos,
- used for other purposes than its original definition.
- }
- begin
- if errno = 0 then { Else it will go through all the cases }
- exit;
- case Errno of
- Sys_ENFILE,
- Sys_EMFILE : Inoutres:=4;
- Sys_ENOENT : Inoutres:=2;
- Sys_EBADF : Inoutres:=6;
- Sys_ENOMEM,
- Sys_EFAULT : Inoutres:=217; //TODO Exchange to something better
- Sys_EINVAL : Inoutres:=218; //TODO RTE 218 doesn't exist
- Sys_EAGAIN,
- Sys_ENOSPC : Inoutres:=101;
- Sys_ENOTDIR : Inoutres:=3;
- Sys_EPERM,
- Sys_EROFS,
- Sys_EEXIST,
- Sys_EISDIR,
- Sys_EINTR, //Happens when attempt to rename a file fails
- Sys_EBUSY, //Happens when attempt to remove a locked file
- Sys_EACCES,
- Sys_ETXTBSY, //Happens when attempt to open an already open file
- Sys_EMLINK : Inoutres:=5; //Happens when attempt to remove open file
- Sys_ENXIO : InOutRes:=152;
- Sys_ESPIPE : InOutRes:=156; //Illegal seek
- else
- InOutRes := Integer(errno);//TODO Exchange to something better
- end;
- errno:=0;
- end;
- Procedure OSErr2InOutRes(err: OSErr);
- { Convert MacOS specific error codes to the correct InOutRes value}
- begin
- if err = noErr then { Else it will go through all the cases }
- exit;
- case err of
- dirFulErr, { Directory full }
- dskFulErr { disk full }
- :Inoutres:=101;
- nsvErr { no such volume }
- :Inoutres:=3;
- ioErr, { I/O error (bummers) }
- bdNamErr { there may be no bad names in the final system! }
- :Inoutres:=1; //TODO Exchange to something better
- fnOpnErr { File not open }
- :Inoutres:=103;
- eofErr, { End of file }
- posErr { tried to position to before start of file (r/w) }
- :Inoutres:=100;
- mFulErr { memory full (open) or file won't fit (load) }
- :Inoutres:=1; //TODO Exchange to something better
- tmfoErr { too many files open}
- :Inoutres:=4;
- fnfErr { File not found }
- :Inoutres:=2;
- wPrErr { diskette is write protected. }
- :Inoutres:=150;
- fLckdErr { file is locked }
- :Inoutres:=5;
- vLckdErr { volume is locked }
- :Inoutres:=150;
- fBsyErr { File is busy (delete) }
- :Inoutres:=5;
- dupFNErr { duplicate filename (rename) }
- :Inoutres:=5;
- opWrErr { file already open with with write permission }
- :Inoutres:=5;
- rfNumErr, { refnum error }
- gfpErr { get file position error }
- :Inoutres:=1; //TODO Exchange to something better
- volOffLinErr { volume not on line error (was Ejected) }
- :Inoutres:=152;
- permErr { permissions error (on file open) }
- :Inoutres:=5;
- volOnLinErr{ drive volume already on-line at MountVol }
- :Inoutres:=0; //TODO Exchange to something other
- nsDrvErr { no such drive (tried to mount a bad drive num) }
- :Inoutres:=1; //TODO Perhaps exchange to something better
- noMacDskErr, { not a mac diskette (sig bytes are wrong) }
- extFSErr { volume in question belongs to an external fs }
- :Inoutres:=157; //TODO Perhaps exchange to something better
- fsRnErr, { file system internal error:during rename the old
- entry was deleted but could not be restored. }
- badMDBErr { bad master directory block }
- :Inoutres:=1; //TODO Exchange to something better
- wrPermErr { write permissions error }
- :Inoutres:=5;
- dirNFErr { Directory not found }
- :Inoutres:=3;
- tmwdoErr { No free WDCB available }
- :Inoutres:=1; //TODO Exchange to something better
- badMovErr { Move into offspring error }
- :Inoutres:=5;
- wrgVolTypErr { Wrong volume type error [operation not
- supported for MFS] }
- :Inoutres:=1; //TODO Exchange to something better
- volGoneErr { Server volume has been disconnected. }
- :Inoutres:=152;
- diffVolErr { files on different volumes }
- :Inoutres:=17;
- catChangedErr { the catalog has been modified }
- { OR comment: when searching with PBCatSearch }
- :Inoutres:=0; //TODO Exchange to something other
- afpAccessDenied, { Insufficient access privileges for operation }
- afpDenyConflict { Specified open/deny modes conflict with current open modes }
- :Inoutres:=5;
- afpNoMoreLocks { Maximum lock limit reached }
- :Inoutres:=5;
- afpRangeNotLocked, { Tried to unlock range that was not locked by user }
- afpRangeOverlap { Some or all of range already locked by same user }
- :Inoutres:=1; //TODO Exchange to something better
- afpObjectTypeErr { File/Directory specified where Directory/File expected }
- :Inoutres:=3;
- afpCatalogChanged { OR comment: when searching with PBCatSearch }
- :Inoutres:=0; //TODO Exchange to something other
- afpSameObjectErr
- :Inoutres:=5; //TODO Exchange to something better
- memFullErr { Not enough room in heap zone }
- :Inoutres:=203;
- else
- InOutRes := 1; //TODO Exchange to something better
- end;
- end;
- function PathArgToFSSpec(s: string; var spec: FSSpec): Boolean;
- var
- err: OSErr;
- begin
- err:= FSMakeFSSpec(curDirectorySpec.vRefNum,
- curDirectorySpec.parID, s, spec);
- if err in [ noErr, fnfErr] then
- PathArgToFSSpec:= true
- else
- begin
- OSErr2InOutRes(err);
- PathArgToFSSpec:= false;
- end;
- end;
- function PathArgToFullPath(s: string; var fullpath: AnsiString): Boolean;
- var
- err: OSErr;
- spec: FSSpec;
- pathHandle: Mac_Handle;
- begin
- PathArgToFullPath:= false;
- if PathArgToFSSpec(s, spec) then
- begin
- err:= FSpGetFullPath(spec, pathHandle, false);
- if err = noErr then
- begin
- SetString(fullpath, pathHandle^, GetHandleSize(pathHandle));
- DisposeHandle(pathHandle);
- PathArgToFullPath:= true;
- end
- else
- OSErr2InOutRes(err);
- end;
- end;
- function FSpLocationFromFullPath(fullPathLength: Integer;
- fullPath: Mac_Ptr; var spec: FSSpec ):OSErr;
- var
- alias: AliasHandle;
- res: OSErr;
- wasChanged: Boolean;
- nullString: Str32;
- begin
- nullString:= '';
- res:= NewAliasMinimalFromFullPath(fullPathLength,
- fullPath, nullString, nullString, alias);
- if res = noErr then
- begin
- res:= ResolveAlias(nil, alias, spec, wasChanged);
- DisposeHandle(Mac_Handle(alias));
- end;
- FSpLocationFromFullPath:= res;
- end;
- {*****************************************************************************
- ParamStr/Randomize
- *****************************************************************************}
- { number of args }
- function paramcount : longint;
- begin
- paramcount := argc - 1;
- //paramcount:=0;
- end;
- { argument number l }
- function paramstr(l : longint) : string;
- begin
- if (l>=0) and (l+1<=argc) then
- paramstr:=strpas(argv[l])
- else
- paramstr:='';
- end;
- { set randseed to a new pseudo random value }
- procedure randomize;
- begin
- randseed:= Cardinal(TickCount);
- end;
- {*****************************************************************************
- Heap Management
- *****************************************************************************}
- var
- { Pointer to a block allocated with the MacOS Memory Manager, which
- is used as the initial FPC heap. }
- theHeap: Mac_Ptr;
- intern_heapsize : longint;external name 'HEAPSIZE';
- { first address of heap }
- function getheapstart:pointer;
- begin
- getheapstart:= theHeap;
- end;
- { current length of heap }
- function getheapsize:longint;
- begin
- getheapsize:= intern_heapsize ;
- end;
- { function to allocate size bytes more for the program }
- { must return the first address of new data space or nil if failed }
- function Sbrk(logicalSize: Longint): Mac_Ptr ;
- external 'InterfaceLib' name 'NewPtr'; //Directly mapped to NewPtr
- { include standard heap management }
- {$I heap.inc}
- {*****************************************************************************
- Low Level File Routines
- ****************************************************************************}
- function do_isdevice(handle:longint):boolean;
- begin
- do_isdevice:=false;
- end;
- { close a file from the handle value }
- procedure do_close(h : longint);
- var
- err: OSErr;
- {No error handling, according to the other targets, which seems reasonable,
- because close might be used to clean up after an error.}
- begin
- {$ifdef MACOS_USE_STDCLIB}
- c_close(h);
- // Errno2InOutRes;
- {$else}
- err:= FSClose(h);
- // OSErr2InOutRes(err);
- {$endif}
- end;
- procedure do_erase(p : pchar);
- {this implementation cannot distinguish between directories and files}
- var
- s: AnsiString;
- begin
- {$ifdef MACOS_USE_STDCLIB}
- if not PathArgToFullPath(p, s) then
- exit;
- remove(PChar(s));
- Errno2InoutRes;
- {$else}
- InOutRes:=1;
- {$endif}
- end;
- procedure do_rename(p1,p2 : pchar);
- var
- s1,s2: AnsiString;
- begin
- {$ifdef MACOS_USE_STDCLIB}
- if not PathArgToFullPath(p1, s1) then
- exit;
- if not PathArgToFullPath(p2, s2) then
- exit;
- c_rename(PChar(s1),PChar(s2));
- Errno2InoutRes;
- {$else}
- InOutRes:=1;
- {$endif}
- end;
- function do_write(h,addr,len : longint) : longint;
- begin
- {$ifdef MACOS_USE_STDCLIB}
- do_write:= c_write(h, pointer(addr), len);
- Errno2InoutRes;
- {$else}
- InOutRes:=1;
- if FSWrite(h, len, Mac_Ptr(addr)) = noErr then
- InOutRes:=0;
- do_write:= len;
- {$endif}
- end;
- function do_read(h,addr,len : longint) : longint;
- var
- i: Longint;
- begin
- {$ifdef MACOS_USE_STDCLIB}
- len:= c_read(h, pointer(addr), len);
- Errno2InoutRes;
- // TEMP BUGFIX Exchange CR to LF.
- for i:= 0 to len-1 do
- if SignedBytePtr(ord(addr) + i)^ = 13 then
- SignedBytePtr(ord(addr) + i)^ := 10;
- do_read:= len;
- {$else}
- InOutRes:=1;
- if FSread(h, len, Mac_Ptr(addr)) = noErr then
- InOutRes:=0;
- do_read:= len;
- {$endif}
- end;
- function do_filepos(handle : longint) : longint;
- var
- pos: Longint;
- begin
- {$ifdef MACOS_USE_STDCLIB}
- {This returns the filepos without moving it.}
- do_filepos := lseek(handle, 0, SEEK_CUR);
- Errno2InoutRes;
- {$else}
- InOutRes:=1;
- if GetFPos(handle, pos) = noErr then
- InOutRes:=0;
- do_filepos:= pos;
- {$endif}
- end;
- procedure do_seek(handle,pos : longint);
- begin
- {$ifdef MACOS_USE_STDCLIB}
- lseek(handle, pos, SEEK_SET);
- Errno2InoutRes;
- {$else}
- InOutRes:=1;
- if SetFPos(handle, fsFromStart, pos) = noErr then
- InOutRes:=0;
- {$endif}
- end;
- function do_seekend(handle:longint):longint;
- begin
- {$ifdef MACOS_USE_STDCLIB}
- lseek(handle, 0, SEEK_END);
- Errno2InoutRes;
- {$else}
- InOutRes:=1;
- if SetFPos(handle, fsFromLEOF, 0) = noErr then
- InOutRes:=0;
- {$endif}
- end;
- function do_filesize(handle : longint) : longint;
- var
- aktfilepos: Longint;
- begin
- {$ifdef MACOS_USE_STDCLIB}
- aktfilepos:= lseek(handle, 0, SEEK_CUR);
- if errno = 0 then
- begin
- do_filesize := lseek(handle, 0, SEEK_END);
- Errno2InOutRes; {Report the error from this operation.}
- lseek(handle, aktfilepos, SEEK_SET); {Always try to move back,
- even in presence of error.}
- end
- else
- Errno2InOutRes;
- {$else}
- InOutRes:=1;
- if GetEOF(handle, pos) = noErr then
- InOutRes:=0;
- do_filesize:= pos;
- {$endif}
- end;
- { truncate at a given position }
- procedure do_truncate (handle,pos:longint);
- begin
- {$ifdef MACOS_USE_STDCLIB}
- ioctl(handle, FIOSETEOF, pointer(pos));
- Errno2InoutRes;
- {$else}
- InOutRes:=1;
- do_seek(handle,pos); //TODO: Is this needed (Does the user anticipate the filemarker is at the end?)
- if SetEOF(handle, pos) = noErr then
- InOutRes:=0;
- {$endif}
- end;
- procedure do_open(var f;p:pchar;flags:longint);
- {
- filerec and textrec have both handle and mode as the first items so
- they could use the same routine for opening/creating.
- when (flags and $100) the file will be append
- when (flags and $1000) the file will be truncate/rewritten
- when (flags and $10000) there is no check for close (needed for textfiles)
- }
- var
- creator, fileType: OSType;
- scriptTag: ScriptCode;
- refNum: Integer;
- res: OSErr;
- fh: Longint;
- oflags : longint;
- s: AnsiString;
- begin
- // AllowSlash(p);
- { close first if opened }
- if ((flags and $10000)=0) then
- begin
- case filerec(f).mode of
- fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
- fmclosed : ;
- else
- begin
- {not assigned}
- inoutres:=102;
- exit;
- end;
- end;
- end;
- { reset file handle }
- filerec(f).handle:=UnusedHandle;
- {$ifdef MACOS_USE_STDCLIB}
- { We do the conversion of filemodes here, concentrated on 1 place }
- case (flags and 3) of
- 0 : begin
- oflags :=O_RDONLY;
- filerec(f).mode:=fminput;
- end;
- 1 : begin
- oflags :=O_WRONLY;
- filerec(f).mode:=fmoutput;
- end;
- 2 : begin
- oflags :=O_RDWR;
- filerec(f).mode:=fminout;
- end;
- end;
- if (flags and $1000)=$1000 then
- oflags:=oflags or (O_CREAT or O_TRUNC)
- else if (flags and $100)=$100 then
- oflags:=oflags or (O_APPEND);
- { empty name is special }
- if p[0]=#0 then
- begin
- case FileRec(f).mode of
- fminput :
- FileRec(f).Handle:=StdInputHandle;
- fminout, { this is set by rewrite }
- fmoutput :
- FileRec(f).Handle:=StdOutputHandle;
- fmappend :
- begin
- FileRec(f).Handle:=StdOutputHandle;
- FileRec(f).mode:=fmoutput; {fool fmappend}
- end;
- end;
- exit;
- end
- else
- begin
- if not PathArgToFullPath(p, s) then
- exit;
- p:= PChar(s);
- end;
- //TODO Perhaps handle readonly filesystems, as in sysunix.inc
- fh:= c_open(p, oflags);
- Errno2InOutRes;
- if fh <> -1 then
- filerec(f).handle:= fh
- else
- filerec(f).handle:= UnusedHandle;
- {$else}
- InOutRes:=1;
- //creator:= $522A6368; {'MPS ' -- MPW}
- //creator:= $74747874; {'ttxt'}
- creator:= $522A6368; {'R*ch' -- BBEdit}
- fileType:= $54455854; {'TEXT'}
- { reset file handle }
- filerec(f).handle:=UnusedHandle;
- res:= FSpLocationFromFullPath(StrLen(p), p, spec);
- if (res = noErr) or (res = fnfErr) then
- begin
- if FSpCreate(spec, creator, fileType, smSystemScript) = noErr then
- ;
- if FSpOpenDF(spec, fsCurPerm, refNum) = noErr then
- begin
- filerec(f).handle:= refNum;
- InOutRes:=0;
- end;
- end;
- if (filerec(f).handle=UnusedHandle) then
- begin
- //errno:=GetLastError;
- //Errno2InoutRes;
- end;
- {$endif}
- end;
- {*****************************************************************************
- UnTyped File Handling
- *****************************************************************************}
- {$i file.inc}
- {*****************************************************************************
- Typed File Handling
- *****************************************************************************}
- {$i typefile.inc}
- {*****************************************************************************
- Text File Handling
- *****************************************************************************}
- { #26 is not end of a file in MacOS ! }
- {$i text.inc}
- {*****************************************************************************
- Directory Handling
- *****************************************************************************}
- procedure mkdir(const s:string);[IOCheck];
- var
- spec: FSSpec;
- createdDirID: Longint;
- err: OSErr;
- begin
- If (s='') or (InOutRes <> 0) then
- exit;
-
- if PathArgToFSSpec(s, spec) then
- begin
- err:= FSpDirCreate(spec, smSystemScript, createdDirID);
- OSErr2InOutRes(err);
- end;
- end;
- procedure rmdir(const s:string);[IOCheck];
- {this implementation cannot distinguish between directories and files}
- var
- spec: FSSpec;
- err: OSErr;
- begin
- If (s='') or (InOutRes <> 0) then
- exit;
- if PathArgToFSSpec(s, spec) then
- begin
- err:= FSpDelete(spec);
- OSErr2InOutRes(err);
- end;
- end;
- procedure chdir(const s:string);[IOCheck];
- var
- spec, newDirSpec: FSSpec;
- err: OSErr;
- begin
- if (s='') or (InOutRes <> 0) then
- exit;
- if PathArgToFSSpec(s, spec) then
- begin
- { The fictive file x is appended to the directory name to make
- FSMakeFSSpec return a FSSpec to a file in the directory.
- Then by clearing the name, the FSSpec then
- points to the directory. It doesn't matter whether x exists or not.}
- err:= FSMakeFSSpec (spec.vRefNum, spec.parID, ':'+spec.name+':x', newDirSpec);
- if err in [ noErr, fnfErr] then
- begin
- curDirectorySpec:= newDirSpec;
- curDirectorySpec.name:='';
- InOutRes:= 0;
- end
- else
- begin
- //E g if the directory doesn't exist.
- OSErr2InOutRes(err);
- end;
- end;
- end;
- procedure getDir (DriveNr: byte; var Dir: ShortString);
- var
- pathHandle: Mac_Handle;
- pathHandleSize: Longint;
- begin
- if FSpGetFullPath(curDirectorySpec, pathHandle, false) <> noErr then
- Halt(3); //exit code 3 according to MPW
- pathHandleSize:= GetHandleSize(pathHandle);
- SetString(dir, pathHandle^, pathHandleSize);
- DisposeHandle(pathHandle);
- if pathHandleSize <= 255 then //because dir is ShortString
- InOutRes := 0
- else
- InOutRes := 1; //TODO Exchange to something better
- end;
- {*****************************************************************************
- SystemUnit Initialization
- *****************************************************************************}
- procedure pascalmain; external name 'PASCALMAIN';
- {Main entry point in C style, needed to capture program parameters.
- For this to work, the system unit must be before the main program
- in the linking order.}
- procedure main(argcparam: Longint; argvparam: ppchar; envpparam: ppchar); cdecl;
- begin
- argc:= argcparam;
- argv:= argvparam;
- envp:= envpparam;
- pascalmain; {run the pascal main program}
- end;
- procedure setup_arguments;
- begin
- //Nothing needs to be done here.
- end;
- procedure setup_environment;
- begin
- end;
- {*****************************************************************************
- System Dependent Exit code
- *****************************************************************************}
- Procedure system_exit;
- begin
- {$ifndef MACOS_USE_STDCLIB}
- if StandAlone <> 0 then
- ExitToShell;
- {$else}
- c_exit(exitcode); //exitcode is only utilized by an MPW tool
- {$endif}
- end;
- procedure SysInitStdIO;
- begin
- { Setup stdin, stdout and stderr }
- {$ifdef MACOS_USE_STDCLIB}
- OpenStdIO(Input,fmInput,StdInputHandle);
- OpenStdIO(Output,fmOutput,StdOutputHandle);
- OpenStdIO(StdOut,fmOutput,StdOutputHandle);
- OpenStdIO(StdErr,fmOutput,StdErrorHandle);
- {$endif }
- end;
- var
- pathHandle: Mac_Handle;
- begin
- if false then //To save it from the dead code stripper
- begin
- //Included only to make them available for debugging in asm.
- Debugger;
- DebugStr('');
- end;
- { To be set if this is a GUI or console application }
- IsConsole := TRUE;
- { To be set if this is a library and not a program }
- IsLibrary := FALSE;
- StackLength := InitialStkLen;
- StackBottom := SPtr - StackLength;
- { Setup working directory }
- if not GetAppFileLocation(curDirectorySpec) then
- Halt(3); //exit code 3 according to MPW
- { Setup heap }
- if Mac_FreeMem - intern_heapsize < 30000 then
- Halt(3); //exit code 3 according to MPW
- theHeap:= Sbrk(intern_heapsize);
- if theHeap = nil then
- Halt(3); //exit code 3 according to MPW
- InitHeap;
- SysInitStdIO;
- { Setup environment and arguments }
- Setup_Environment;
- setup_arguments;
- { Reset IO Error }
- InOutRes:=0;
- errno:=0;
- {$ifdef HASVARIANT}
- initvariantmanager;
- {$endif HASVARIANT}
- end.
- {
- $Log$
- Revision 1.10 2003-10-29 22:34:52 olle
- + handles program parameters for MPW
- + program start stub
- * improved working directory handling
- * minor changes
- + some documentation
- Revision 1.9 2003/10/17 23:44:30 olle
- + working direcory emulated
- + implemented directory handling procs
- + all proc which take a path param, now resolve it relative wd
- Revision 1.8 2003/10/16 15:43:13 peter
- * THandle is platform dependent
- Revision 1.7 2003/09/27 11:52:35 peter
- * sbrk returns pointer
- Revision 1.6 2003/09/12 12:45:15 olle
- + filehandling complete
- + heaphandling complete
- + support for random
- * filehandling now uses filedecriptors in StdCLib
- * other minor changes
- - removed DEFINE MAC_SYS_RUNNABLE
- Revision 1.5 2003/01/13 17:18:55 olle
- + added support for rudimentary file handling
- Revision 1.4 2002/11/28 10:58:02 olle
- + added support for rudimentary heap
- Revision 1.3 2002/10/23 15:29:09 olle
- + added switch MAC_SYS_RUNABLE
- + added include of system.h etc
- + added standard globals
- + added dummy hook procedures
- Revision 1.2 2002/10/10 19:44:05 florian
- * changes from Olle to compile/link a simple program
- Revision 1.1 2002/10/02 21:34:31 florian
- * first dummy implementation
- }
|