123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 2004 by Karoly Balogh for Genesi S.a.r.l.
- System unit for MorphOS/PowerPC
- Uses parts of the Commodore Amiga/68k port by Carl Eric Codere
- and Nils Sjoholm
- MorphOS port was done on a free Pegasos II/G4 machine
- provided by Genesi S.a.r.l. <www.genesi.lu>
- 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
- {$define FPC_IS_SYSTEM}
- {$I systemh.inc}
- const
- LineEnding = #10;
- LFNSupport = True;
- DirectorySeparator = '/';
- DriveSeparator = ':';
- ExtensionSeparator = '.';
- PathSeparator = ';';
- AllowDirectorySeparators : set of char = ['\','/'];
- AllowDriveSeparators : set of char = [':'];
- maxExitCode = 255;
- MaxPathLen = 256;
- AllFilesMask = '#?';
- const
- UnusedHandle : LongInt = -1;
- StdInputHandle : LongInt = 0;
- StdOutputHandle : LongInt = 0;
- StdErrorHandle : LongInt = 0;
- FileNameCaseSensitive : Boolean = False;
- CtrlZMarksEOF: boolean = false; { #26 not considered as end of file }
- sLineBreak : string[1] = LineEnding;
- DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsLF;
- BreakOn : Boolean = True;
- var
- MOS_ExecBase : Pointer; external name '_ExecBase';
- MOS_DOSBase : Pointer;
- MOS_UtilityBase: Pointer;
- MOS_heapPool : Pointer; { pointer for the OS pool for growing the heap }
- MOS_origDir : LongInt; { original directory on startup }
- MOS_ambMsg : Pointer;
- MOS_ConName : PChar ='CON:10/30/620/100/FPC Console Output/AUTO/CLOSE/WAIT';
- MOS_ConHandle: LongInt;
- argc: LongInt;
- argv: PPChar;
- envp: PPChar;
- implementation
- {$I system.inc}
- {$IFDEF MOSFPC_FILEDEBUG}
- {$WARNING Compiling with file debug enabled!}
- {$ENDIF}
- {$IFDEF MOSFPC_MEMDEBUG}
- {$WARNING Compiling with memory debug enabled!}
- {$ENDIF}
- {*****************************************************************************
- Misc. System Dependent Functions
- *****************************************************************************}
- procedure haltproc(e:longint);cdecl;external name '_haltproc';
- procedure System_exit;
- begin
- { We must remove the CTRL-C FLAG here because halt }
- { may call I/O routines, which in turn might call }
- { halt, so a recursive stack crash }
- if BreakOn then begin
- if (SetSignal(0,0) and SIGBREAKF_CTRL_C)<>0 then
- SetSignal(0,SIGBREAKF_CTRL_C);
- end;
- { Closing opened files }
- CloseList(MOS_fileList);
- { Changing back to original directory if changed }
- if MOS_origDir<>0 then begin
- CurrentDir(MOS_origDir);
- end;
- { Closing CON: when in Ambient mode }
- if MOS_ConHandle<>0 then dosClose(MOS_ConHandle);
- if MOS_UtilityBase<>nil then CloseLibrary(MOS_UtilityBase);
- if MOS_DOSBase<>nil then CloseLibrary(MOS_DOSBase);
- if MOS_heapPool<>nil then DeletePool(MOS_heapPool);
- { If in Ambient mode, replying WBMsg }
- if MOS_ambMsg<>nil then begin
- Forbid;
- ReplyMsg(MOS_ambMsg);
- end;
- haltproc(ExitCode);
- end;
- { Generates correct argument array on startup }
- procedure GenerateArgs;
- var
- argvlen : longint;
- procedure allocarg(idx,len:longint);
- var
- i,oldargvlen : longint;
- begin
- if idx>=argvlen then
- begin
- oldargvlen:=argvlen;
- argvlen:=(idx+8) and (not 7);
- sysreallocmem(argv,argvlen*sizeof(pointer));
- for i:=oldargvlen to argvlen-1 do
- argv[i]:=nil;
- end;
- ArgV [Idx] := SysAllocMem (Succ (Len));
- end;
- var
- count: word;
- start: word;
- localindex: word;
- p : pchar;
- temp : string;
- begin
- p:=GetArgStr;
- argvlen:=0;
- { Set argv[0] }
- temp:=paramstr(0);
- allocarg(0,length(temp));
- move(temp[1],argv[0]^,length(temp));
- argv[0][length(temp)]:=#0;
- { check if we're started from Ambient }
- if MOS_ambMsg<>nil then begin
- argc:=0;
- exit;
- end;
- { Handle the other args }
- count:=0;
- { first index is one }
- localindex:=1;
- while (p[count]<>#0) do
- begin
- while (p[count]=' ') or (p[count]=#9) or (p[count]=LineEnding) do inc(count);
- start:=count;
- while (p[count]<>#0) and (p[count]<>' ') and (p[count]<>#9) and (p[count]<>LineEnding) do inc(count);
- if (count-start>0) then
- begin
- allocarg(localindex,count-start);
- move(p[start],argv[localindex]^,count-start);
- argv[localindex][count-start]:=#0;
- inc(localindex);
- end;
- end;
- argc:=localindex;
- end;
- function GetProgDir: String;
- var
- s1 : String;
- alock : LongInt;
- counter: Byte;
- begin
- GetProgDir:='';
- FillChar(s1,255,#0);
- { GetLock of program directory }
- alock:=GetProgramDir;
- if alock<>0 then begin
- if NameFromLock(alock,@s1[1],255) then begin
- counter:=1;
- while (s1[counter]<>#0) and (counter<>0) do Inc(counter);
- s1[0]:=Char(counter-1);
- GetProgDir:=s1;
- end;
- end;
- end;
- function GetProgramName: String;
- { Returns ONLY the program name }
- var
- s1 : String;
- counter: Byte;
- begin
- GetProgramName:='';
- FillChar(s1,255,#0);
- if GetProgramName(@s1[1],255) then begin
- { now check out and assign the length of the string }
- counter := 1;
- while (s1[counter]<>#0) and (counter<>0) do Inc(counter);
- s1[0]:=Char(counter-1);
- { now remove any component path which should not be there }
- for counter:=length(s1) downto 1 do
- if (s1[counter] = '/') or (s1[counter] = ':') then break;
- { readjust counterv to point to character }
- if counter<>1 then Inc(counter);
- GetProgramName:=copy(s1,counter,length(s1));
- end;
- end;
- function GetArgv0Ambient: String;
- { Returns program full path+name, when in Ambient mode }
- { Required for paramstr(0) support in Ambient mode }
- type
- pWBArg = ^tWBArg;
- tWBArg = record
- wa_Lock: longint;
- wa_Name: PChar;
- end;
- pWBStartup = ^tWBStartup;
- tWBStartup = packed record
- sm_Message : tMessage;
- sm_Process : pMsgPort;
- sm_Segment : longint;
- sm_NumArgs : longint;
- sm_ToolWindow: PChar;
- sm_ArgList : pWBArg;
- end;
- var
- tmpbuf : String;
- counter : longint;
- progname: PChar;
- dlock : longint;
- begin
- GetArgv0Ambient:='';
- if MOS_ambMsg<>nil then begin
- dlock:=pWBStartup(MOS_ambMsg)^.sm_argList^.wa_Lock;
- if dlock<>0 then begin
- FillDWord(tmpbuf,256 div 4,0);
- if NameFromLock(dlock,@tmpbuf[1],255) then begin
- counter:=1;
- while tmpbuf[counter]<>#0 do
- inc(counter);
- tmpbuf[0]:=Char(counter-1);
- GetArgv0Ambient:=tmpbuf;
- { Append slash,if we're not in root directory of a volume }
- if tmpbuf[counter-1]<>':' then
- GetArgv0Ambient:=GetArgv0Ambient+'/';
- end;
- end;
- { Fetch the progname, and copy it to the buffer }
- progname:=pWBStartup(MOS_ambMsg)^.sm_argList^.wa_Name;
- if progname<>nil then begin
- FillDWord(tmpbuf,256 div 4,0);
- counter:=0;
- while (progname[counter]<>#0) do begin
- tmpbuf[counter+1]:=progname[counter];
- inc(counter);
- end;
- tmpbuf[0]:=Char(counter);
- GetArgv0Ambient:=GetArgv0Ambient+tmpbuf;
- end;
- end;
- end;
- {*****************************************************************************
- ParamStr/Randomize
- *****************************************************************************}
- { number of args }
- function paramcount : longint;
- begin
- if MOS_ambMsg<>nil then
- paramcount:=0
- else
- paramcount:=argc-1;
- end;
- { argument number l }
- function paramstr(l : longint) : string;
- var
- s1: String;
- begin
- paramstr:='';
- if MOS_ambMsg<>nil then begin
- if l=0 then begin
- paramstr:=GetArgv0Ambient;
- exit;
- end else
- exit;
- end;
- if l=0 then begin
- s1:=GetProgDir;
- if s1[length(s1)]=':' then paramstr:=s1+GetProgramName
- else paramstr:=s1+'/'+GetProgramName;
- end else begin
- if (l>0) and (l+1<=argc) then paramstr:=strpas(argv[l]);
- end;
- end;
- { set randseed to a new pseudo random value }
- procedure randomize;
- var tmpTime: TDateStamp;
- begin
- DateStamp(@tmpTime);
- randseed:=tmpTime.ds_tick;
- end;
- { MorphOS specific startup }
- procedure SysInitMorphOS;
- var self: PProcess;
- begin
- self:=PProcess(FindTask(nil));
- if self^.pr_CLI=0 then begin
- { if we're running from Ambient/Workbench, we catch its message }
- WaitPort(@self^.pr_MsgPort);
- MOS_ambMsg:=GetMsg(@self^.pr_MsgPort);
- end;
- MOS_DOSBase:=OpenLibrary('dos.library',50);
- if MOS_DOSBase=nil then Halt(1);
- MOS_UtilityBase:=OpenLibrary('utility.library',50);
- if MOS_UtilityBase=nil then Halt(1);
- { Creating the memory pool for growing heap }
- MOS_heapPool:=CreatePool(MEMF_FAST,growheapsize2,growheapsize1);
- if MOS_heapPool=nil then Halt(1);
- if MOS_ambMsg=nil then begin
- MOS_ConHandle:=0;
- StdInputHandle:=dosInput;
- StdOutputHandle:=dosOutput;
- end else begin
- MOS_ConHandle:=Open(MOS_ConName,MODE_OLDFILE);
- if MOS_ConHandle<>0 then begin
- StdInputHandle:=MOS_ConHandle;
- StdOutputHandle:=MOS_ConHandle;
- end else
- Halt(1);
- end;
- end;
- procedure SysInitStdIO;
- begin
- OpenStdIO(Input,fmInput,StdInputHandle);
- OpenStdIO(Output,fmOutput,StdOutputHandle);
- OpenStdIO(StdOut,fmOutput,StdOutputHandle);
- { * MorphOS doesn't have a separate stderr, just like AmigaOS (???) * }
- StdErrorHandle:=StdOutputHandle;
- // OpenStdIO(StdErr,fmOutput,StdErrorHandle);
- // OpenStdIO(ErrOutput,fmOutput,StdErrorHandle);
- end;
- function GetProcessID: SizeUInt;
- begin
- GetProcessID:=SizeUInt(FindTask(NIL));
- end;
- function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
- begin
- result := stklen;
- end;
- begin
- IsConsole := TRUE;
- StackLength := CheckInitialStkLen(InitialStkLen);
- StackBottom := Sptr - StackLength;
- SysResetFPU;
- if not(IsLibrary) then
- SysInitFPU;
- { OS specific startup }
- MOS_ambMsg:=nil;
- MOS_origDir:=0;
- MOS_fileList:=nil;
- envp:=nil;
- SysInitMorphOS;
- { Set up signals handlers }
- // InstallSignals;
- { Setup heap }
- InitHeap;
- SysInitExceptions;
- { Setup stdin, stdout and stderr }
- SysInitStdIO;
- { Reset IO Error }
- InOutRes:=0;
- { Arguments }
- GenerateArgs;
- InitSystemThreads;
- initvariantmanager;
- {$ifdef VER2_2}
- initwidestringmanager;
- {$else VER2_2}
- initunicodestringmanager;
- {$endif VER2_2}
- end.
|