+ handles program parameters for MPW

+ program start stub
  * improved working directory handling
  * minor changes
  + some documentation
This commit is contained in:
olle 2003-10-29 22:34:52 +00:00
parent 6a06df943b
commit 00065dd24d

View File

@ -33,7 +33,7 @@ const
LFNSupport = true;
DirectorySeparator = ':';
DriveSeparator = ':';
PathSeparator = ','; // Is used in MPW
PathSeparator = ','; // Is used in MPW and OzTeX
FileNameCaseSensitive = false;
{ include heap support headers }
@ -54,8 +54,86 @@ var
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}
@ -71,9 +149,6 @@ as an include file and not a unit.}
{$I macostp.inc}
{TODO: Perhaps the System unit should check the MacOS version to
ensure it is a supported version. }
{$ifdef MACOS_USE_STDCLIB}
{************** API to StdCLib in MacOS ***************}
@ -126,36 +201,35 @@ const
TIOFLUSH = $00007408; // discard unread input. arg is ignored
function C_open(path: PChar; oflag: C_int): C_int;
function c_open(path: PChar; oflag: C_int): C_int; cdecl;
external 'StdCLib' name 'open';
function C_close(filedes: C_int): C_int;
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;
function c_write(filedes: C_int; buf: pointer; nbyte: size_t): size_t; cdecl;
external 'StdCLib' name 'write';
{??? fread returns only when n items has been read. Does not specifically
return after newlines, so cannot be used for reading input from the console.}
function C_read(filedes: C_int; buf: pointer; nbyte: size_t): size_t;
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;
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;
function ioctl(filedes: C_int; cmd: C_unsigned_int; arg: pointer): C_int; cdecl;
external 'StdCLib' name 'ioctl';
function remove(filename: PChar): C_int;
function remove(filename: PChar): C_int; cdecl;
external 'StdCLib';
function c_rename(old, c_new: PChar): C_int;
function c_rename(old, c_new: PChar): C_int; cdecl;
external 'StdCLib' name 'rename';
procedure c_exit(status: C_int);
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';
@ -205,17 +279,9 @@ Sys_ERANGE = 34; { Math result not representable }
{******************************************************}
var
{working directory}
curDirectorySpec: FSSpec;
{Note about working directory. There is a facility in MacOS to
set a working directory. However, this requires the application
to have a unique application signature (creator code), to distinguish
its working directory from working directory of other applications.
Due to the fact that applications might be anonymous (without an
application signature), this facility will not work. Hence we
will manage working directory by our self.}
function GetAppFileLocation (var spec: FSSpec): Boolean;
//Requires >= System 7
@ -487,6 +553,27 @@ begin
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
*****************************************************************************}
@ -494,16 +581,16 @@ end;
{ number of args }
function paramcount : longint;
begin
{paramcount := argc - 1;}
paramcount:=0;
paramcount := argc - 1;
//paramcount:=0;
end;
{ argument number l }
function paramstr(l : longint) : string;
begin
{if (l>=0) and (l+1<=argc) then
if (l>=0) and (l+1<=argc) then
paramstr:=strpas(argv[l])
else}
else
paramstr:='';
end;
@ -555,18 +642,22 @@ 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;
c_close(h);
// Errno2InOutRes;
{$else}
InOutRes:=1;
if FSClose(h) = noErr then
InOutRes:=0;
err:= FSClose(h);
// OSErr2InOutRes(err);
{$endif}
end;
procedure do_erase(p : pchar);
{this implementation cannot distinguish between directories and files}
var
s: AnsiString;
begin
@ -599,7 +690,7 @@ end;
function do_write(h,addr,len : longint) : longint;
begin
{$ifdef MACOS_USE_STDCLIB}
do_write:= C_write(h, pointer(addr), len);
do_write:= c_write(h, pointer(addr), len);
Errno2InoutRes;
{$else}
InOutRes:=1;
@ -616,7 +707,7 @@ var
begin
{$ifdef MACOS_USE_STDCLIB}
len:= C_read(h, pointer(addr), len);
len:= c_read(h, pointer(addr), len);
Errno2InoutRes;
// TEMP BUGFIX Exchange CR to LF.
@ -715,27 +806,6 @@ begin
{$endif}
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;
procedure do_open(var f;p:pchar;flags:longint);
{
filerec and textrec have both handle and mode as the first items so
@ -824,10 +894,11 @@ begin
p:= PChar(s);
end;
fh:= C_open(p, oflags);
//TODO Perhaps handle readonly filesystems, as in sysunix.inc
fh:= c_open(p, oflags);
Errno2InOutRes;
if fh <> -1 then
filerec(f).handle:= fh
else
@ -846,7 +917,7 @@ begin
res:= FSpLocationFromFullPath(StrLen(p), p, spec);
if (res = noErr) or (res = fnfErr) then
begin
begin
if FSpCreate(spec, creator, fileType, smSystemScript) = noErr then
;
@ -854,7 +925,7 @@ begin
begin
filerec(f).handle:= refNum;
InOutRes:=0;
end;
end;
end;
if (filerec(f).handle=UnusedHandle) then
@ -865,8 +936,6 @@ begin
{$endif}
end;
{*****************************************************************************
UnTyped File Handling
*****************************************************************************}
@ -883,8 +952,7 @@ end;
Text File Handling
*****************************************************************************}
{ should we consider #26 as the end of a file ? }
{?? $DEFINE EOF_CTRLZ}
{ #26 is not end of a file in MacOS ! }
{$i text.inc}
@ -896,19 +964,20 @@ 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
if FSpDirCreate(spec, smSystemScript, createdDirID) = noErr then
InOutRes:= 0
else
InOutRes:= 1;
begin
err:= FSpDirCreate(spec, smSystemScript, createdDirID);
OSErr2InOutRes(err);
end;
end;
procedure rmdir(const s:string);[IOCheck];
//Kolla att endast directories tas bort, kolla med dok.
{this implementation cannot distinguish between directories and files}
var
spec: FSSpec;
err: OSErr;
@ -925,42 +994,72 @@ end;
procedure chdir(const s:string);[IOCheck];
var
newDirSpec: FSSpec;
spec, newDirSpec: FSSpec;
err: OSErr;
begin
If (s='') or (InOutRes <> 0) then
if (s='') or (InOutRes <> 0) then
exit;
InOutRes:=1;
if FSMakeFSSpec (curDirectorySpec.vRefNum, curDirectorySpec.parID,
s+':x', newDirSpec) in [ noErr, fnfErr] then
{ the fictive file x is appended to the path to make FSMakeFSSpec return a FSSpec
to a file in the directory. Then by clearing the name, the FSSpec then
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.}
begin
curDirectorySpec:= newDirSpec;
curDirectorySpec.name:='';
InOutRes:= 0;
end;
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
SetString(dir, pathHandle^, GetHandleSize(pathHandle));
pathHandleSize:= GetHandleSize(pathHandle);
SetString(dir, pathHandle^, pathHandleSize);
DisposeHandle(pathHandle);
InOutRes := 0;
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;
@ -1039,7 +1138,14 @@ end.
{
$Log$
Revision 1.9 2003-10-17 23:44:30 olle
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