unit system; interface {$DEFINE FPC_NO_DEFAULT_HEAP} {$DEFINE FPC_INCLUDE_SOFTWARE_MUL} {$DEFINE FPC_INCLUDE_SOFTWARE_MOD_DIV} {$DEFINE FPC_USE_SMALL_DEFAULTSTACKSIZE} { To avoid warnings in thread.inc code, but value must be really given after systemh.inc is included otherwise the $mode switch is not effective } {$DEFINE HAS_CMDLINE} {$I systemh.inc} {$IFDEF FPC_X86_DATA_NEAR} {$I locheaph.inc} {$ELSE FPC_X86_DATA_NEAR} { todo: implement a working win16 heap manager for the far data models } {$I tnyheaph.inc} {$ENDIF FPC_X86_DATA_NEAR} const LineEnding = #13#10; { LFNSupport is a variable here, defined below!!! } DirectorySeparator = '\'; DriveSeparator = ':'; ExtensionSeparator = '.'; PathSeparator = ';'; AllowDirectorySeparators : set of char = ['\','/']; AllowDriveSeparators : set of char = [':']; { FileNameCaseSensitive and FileNameCasePreserving are defined separately below!!! } maxExitCode = 255; MaxPathLen = 256; const { Default filehandles } UnusedHandle = $ffff;{ instead of -1, as it is a word value} StdInputHandle = 0; StdOutputHandle = 1; StdErrorHandle = 2; FileNameCaseSensitive : boolean = false; FileNameCasePreserving: boolean = false; CtrlZMarksEOF: boolean = true; (* #26 is considered as end of file *) sLineBreak = LineEnding; DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsCRLF; { Default memory segments (Tp7 compatibility) } { seg0040: Word = $0040; segA000: Word = $A000; segB000: Word = $B000; segB800: Word = $B800;} type LPSTR = ^Char;far; PFarChar = ^Char;far; PHugeChar = ^Char;huge; var { Mem[] support } mem : array[0..$7fff-1] of byte absolute $0:$0; memw : array[0..($7fff div sizeof(word))-1] of word absolute $0:$0; meml : array[0..($7fff div sizeof(longint))-1] of longint absolute $0:$0; { C-compatible arguments and environment } argc:longint; //!! public name 'operatingsystem_parameter_argc'; argv:PPchar; //!! public name 'operatingsystem_parameter_argv'; envp:PPchar; //!! public name 'operatingsystem_parameter_envp'; dos_argv0 : pchar; //!! public name 'dos_argv0'; { The DOS Program Segment Prefix segment (TP7 compatibility) } PrefixSeg:Word;public name '__fpc_PrefixSeg'; { BP7 compatible windows variables } { In C, these are the parameters to WinMain } CmdLine: LPSTR;public name '__fpc_CmdLine'; CmdShow: SmallInt;public name '__fpc_CmdShow'; HInstance: Word{HINST};public name '__fpc_HInstance'; HPrevInst: Word{HINST};public name '__fpc_HPrevInst'; { The value that needs to be added to the segment to move the pointer by 64K bytes (BP7 compatibility) } SelectorInc: Word;public name '__fpc_SelectorInc'; { SaveInt00: FarPointer;public name '__SaveInt00';} AllFilesMask: string [3]; {$ifndef RTLLITE} { System info } LFNSupport : boolean; {$ELSE RTLLITE} const LFNSupport = false; {$endif RTLLITE} procedure MessageBox(hWnd: word; lpText, lpCaption: LPSTR; uType: word);external 'USER'; implementation const fCarry = 1; { used for an offset fixup for accessing the proc parameters in asm routines that use nostackframe. We can't use the parameter name directly, because i8086 doesn't support sp relative addressing. } {$ifdef FPC_X86_CODE_FAR} extra_param_offset = 2; {$else FPC_X86_CODE_FAR} extra_param_offset = 0; {$endif FPC_X86_CODE_FAR} {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)} extra_data_offset = 2; {$else} extra_data_offset = 0; {$endif} type PFarByte = ^Byte;far; PFarWord = ^Word;far; { structure, located at DS:0, initialized by InitTask } PAutoDataSegHeader = ^TAutoDataSegHeader; TAutoDataSegHeader = record null: Word; oOldSP: Word; hOldSS: Word; pLocalHeap: Word; pAtomTable: Word; pStackTop: Word; pStackMin: Word; pStackBot: Word; end; {$I registers.inc} procedure MsDos(var Regs: Registers); external name 'FPC_MSDOS'; { invokes int 21h with the carry flag set on entry; used for the LFN functions to ensure that the carry flag is set on exit on older DOS versions which don't support them } procedure MsDos_Carry(var Regs: Registers); external name 'FPC_MSDOS_CARRY'; {$define SYSTEMUNIT} {$I wintypes.inc} {$I winprocsh.inc} {$I winprocs.inc} {$I system.inc} {$IFDEF FPC_X86_DATA_NEAR} {$I locheap.inc} {$ELSE FPC_X86_DATA_NEAR} { todo: implement a working win16 heap manager for the far data models } {$I tinyheap.inc} {$ENDIF FPC_X86_DATA_NEAR} {***************************************************************************** ParamStr/Randomize *****************************************************************************} {function GetProgramName: string; var dos_env_seg: Word; ofs: Word; Ch, Ch2: Char; begin if dos_version < $300 then begin GetProgramName := ''; exit; end; dos_env_seg := PFarWord(Ptr(PrefixSeg, $2C))^; ofs := 1; repeat Ch := PFarChar(Ptr(dos_env_seg,ofs - 1))^; Ch2 := PFarChar(Ptr(dos_env_seg,ofs))^; if (Ch = #0) and (Ch2 = #0) then begin Inc(ofs, 3); GetProgramName := ''; repeat Ch := PFarChar(Ptr(dos_env_seg,ofs))^; if Ch <> #0 then GetProgramName := GetProgramName + Ch; Inc(ofs); if ofs = 0 then begin GetProgramName := ''; exit; end; until Ch = #0; exit; end; Inc(ofs); if ofs = 0 then begin GetProgramName := ''; exit; end; until false; end;} function GetArg(ArgNo: Integer; out ArgResult: string): Integer; var I: Integer; InArg: Boolean; begin ArgResult := ''; I := 0; InArg := False; GetArg := 0; while CmdLine[I]<>#0 do begin if not InArg and (CmdLine[I] <> ' ') then begin InArg := True; Inc(GetArg); end; if InArg and (CmdLine[I] = ' ') then InArg := False; if InArg and (GetArg = ArgNo) then ArgResult := ArgResult + CmdLine[I]; Inc(I); end; end; function paramcount : longint; var tmpstr: string; begin paramcount := GetArg(-1, tmpstr); end; function paramstr(l : longint) : string; begin if l = 0 then paramstr := ''{GetProgramName} else GetArg(l, paramstr); end; procedure randomize; {var hl : longint; regs : Registers;} begin { regs.AH:=$2C; MsDos(regs); hl:=regs.DX; randseed:=hl*$10000+ regs.CX;} end; {***************************************************************************** System Dependent Exit code *****************************************************************************} procedure system_exit; {var h : byte;} begin (* RestoreInterruptHandlers; for h:=0 to max_files-1 do if openfiles[h] then begin {$ifdef SYSTEMDEBUG} writeln(stderr,'file ',opennames[h],' not closed at exit'); {$endif SYSTEMDEBUG} if h>=5 then do_close(h); end; {$ifndef FPC_MM_TINY} if not CheckNullArea then writeln(stderr, 'Nil pointer assignment'); {$endif FPC_MM_TINY}*) asm mov al, byte [exitcode] mov ah, 4Ch int 21h end; end; {***************************************************************************** SystemUnit Initialization *****************************************************************************} procedure InitWin16Heap; begin {$ifdef FPC_X86_DATA_NEAR} SetMemoryManager(LocalHeapMemoryManager); {$else FPC_X86_DATA_NEAR} { todo: implement a working win16 heap manager for the far data models } {$endif FPC_X86_DATA_NEAR} end; function CheckLFN:boolean; var regs : Registers; RootName : pchar; buf : array [0..31] of char; begin { Check LFN API on drive c:\ } RootName:='C:\'; { Call 'Get Volume Information' ($71A0) } FillChar(regs,SizeOf(regs),0); regs.AX:=$71a0; regs.ES:=Seg(buf); regs.DI:=Ofs(buf); regs.CX:=32; regs.DS:=Seg(RootName^); regs.DX:=Ofs(RootName^); MsDos_Carry(regs); { If carryflag=0 and LFN API bit in ebx is set then use Long file names } CheckLFN:=(regs.Flags and fCarry=0) and (regs.BX and $4000=$4000); end; procedure SysInitStdIO; begin OpenStdIO(Input,fmInput,StdInputHandle); OpenStdIO(Output,fmOutput,StdOutputHandle); OpenStdIO(ErrOutput,fmOutput,StdErrorHandle); OpenStdIO(StdOut,fmOutput,StdOutputHandle); OpenStdIO(StdErr,fmOutput,StdErrorHandle); end; function GetProcessID: SizeUInt; begin GetProcessID := PrefixSeg; end; function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt; begin result := stklen; end; begin {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)} with PAutoDataSegHeader(Ptr(DSeg,0))^ do begin StackBottom := Ptr(SSeg,pStackTop); StackLength := pStackBot-pStackTop; end; {$else} with PAutoDataSegHeader(0)^ do begin StackBottom := NearPointer(pStackTop); StackLength := pStackBot-pStackTop; end; {$endif} { To be set if this is a GUI or console application } IsConsole := FALSE; { To be set if this is a library and not a program } IsLibrary := FALSE; { Setup heap } InitWin16Heap; SysInitExceptions; initunicodestringmanager; { Use LFNSupport LFN } LFNSupport:=CheckLFN; if LFNSupport then begin FileNameCasePreserving:=true; AllFilesMask := '*'; end else AllFilesMask := '*.*'; { Reset IO Error } InOutRes:=0; end.