mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 05:59:37 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			795 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			795 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    This file is part of the Free Pascal run time library.
 | 
						|
    Copyright (c) 1999-2000 by the Free Pascal development team.
 | 
						|
 | 
						|
    Watcom
 | 
						|
 | 
						|
    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
 | 
						|
 | 
						|
{$ifndef NO_EXCEPTIONS_IN_SYSTEM}
 | 
						|
{$define EXCEPTIONS_IN_SYSTEM}
 | 
						|
{$endif NO_EXCEPTIONS_IN_SYSTEM}
 | 
						|
 | 
						|
{$define FPC_ANSI_TEXTFILEREC}
 | 
						|
{ include system-independent routine headers }
 | 
						|
 | 
						|
{ wasm does not support SSE3 instructions }
 | 
						|
{$define FASTMOVE_DISABLE_SSE3}
 | 
						|
 | 
						|
{$include systemh.inc}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
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    = -1;
 | 
						|
  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 = $0040;
 | 
						|
  segA000 = $A000;
 | 
						|
  segB000 = $B000;
 | 
						|
  segB800 = $B800;
 | 
						|
 | 
						|
var
 | 
						|
{ Mem[] support }
 | 
						|
  mem  : array[0..$7fffffff-1] of byte absolute $0:$0;
 | 
						|
  memw : array[0..($7fffffff div sizeof(word)) -1] of word absolute $0:$0;
 | 
						|
  meml : array[0..($7fffffff div sizeof(longint)) -1] of longint absolute $0:$0;
 | 
						|
{ C-compatible arguments and environment }
 | 
						|
  argc  : longint;
 | 
						|
  argv  : ppchar;
 | 
						|
  envp  : ppchar;
 | 
						|
  dos_argv0 : pchar;
 | 
						|
 | 
						|
  AllFilesMask: string [3];
 | 
						|
 | 
						|
{$ifndef RTLLITE}
 | 
						|
{ System info }
 | 
						|
  LFNSupport : boolean;
 | 
						|
{$ELSE RTLLITE}
 | 
						|
Const
 | 
						|
  LFNSupport = false;
 | 
						|
{$endif RTLLITE}
 | 
						|
 | 
						|
{
 | 
						|
  necessary for objects.pas, should be removed (at least from the interface
 | 
						|
  to the implementation)
 | 
						|
}
 | 
						|
  type
 | 
						|
    trealregs=record
 | 
						|
      realedi,realesi,realebp,realres,
 | 
						|
      realebx,realedx,realecx,realeax : longint;
 | 
						|
      realflags,
 | 
						|
      reales,realds,realfs,realgs,
 | 
						|
      realip,realcs,realsp,realss  : word;
 | 
						|
    end;
 | 
						|
  function  do_write(h:longint;addr:pointer;len : longint) : longint;
 | 
						|
  function  do_read(h:longint;addr:pointer;len : longint) : longint;
 | 
						|
  procedure syscopyfromdos(addr : sizeuint; len : longint);
 | 
						|
  procedure syscopytodos(addr : sizeuint; len : longint);
 | 
						|
  procedure sysrealintr(intnr : word;var regs : trealregs);
 | 
						|
 | 
						|
  var tb:longint;
 | 
						|
      tb_segment:word;
 | 
						|
 | 
						|
  const tb_offset=0;
 | 
						|
        tb_size=8192;
 | 
						|
 | 
						|
IMPLEMENTATION
 | 
						|
 | 
						|
{ include system independent routines }
 | 
						|
 | 
						|
{$include system.inc}
 | 
						|
 | 
						|
 | 
						|
{$asmmode ATT}
 | 
						|
 | 
						|
var psp_selector:word; external name 'PSP_SELECTOR';
 | 
						|
 | 
						|
procedure setup_arguments;
 | 
						|
type
 | 
						|
  arrayword = array [0..255] of word;
 | 
						|
var
 | 
						|
  proxy_s  : string[50];
 | 
						|
  proxy_argc,proxy_seg,proxy_ofs,lin : longint;
 | 
						|
  rm_argv  : ^arrayword;
 | 
						|
  argv0len : longint;
 | 
						|
  useproxy : boolean;
 | 
						|
  hp       : ppchar;
 | 
						|
  doscmd   : string[129];  { Dos commandline copied from PSP, max is 128 chars +1 for terminating zero }
 | 
						|
  arglen,
 | 
						|
  count   : longint;
 | 
						|
  argstart,
 | 
						|
  pc,arg  : pchar;
 | 
						|
  quote   : char;
 | 
						|
  argvlen : longint;
 | 
						|
 | 
						|
  function atohex(s : pchar) : longint;
 | 
						|
  var
 | 
						|
    rv : longint;
 | 
						|
    v  : byte;
 | 
						|
  begin
 | 
						|
    rv:=0;
 | 
						|
    while (s^<>#0) do
 | 
						|
     begin
 | 
						|
       v:=byte(s^)-byte('0');
 | 
						|
       if (v > 9) then
 | 
						|
         dec(v,7);
 | 
						|
       v:=v and 15; { in case it's lower case }
 | 
						|
       rv:=(rv shl 4) or v;
 | 
						|
       inc(longint(s));
 | 
						|
     end;
 | 
						|
    atohex:=rv;
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure allocarg(idx,len:longint);
 | 
						|
  var oldargvlen:longint;
 | 
						|
  begin
 | 
						|
    if idx>=argvlen then
 | 
						|
     begin
 | 
						|
       oldargvlen:=argvlen;
 | 
						|
       argvlen:=(idx+8) and (not 7);
 | 
						|
       sysreallocmem(argv,argvlen*sizeof(pointer));
 | 
						|
       fillchar(argv[oldargvlen],(argvlen-oldargvlen)*sizeof(pointer),0);
 | 
						|
       argv[idx]:=nil;
 | 
						|
     end;
 | 
						|
     ArgV [Idx] := SysAllocMem (Succ (Len));
 | 
						|
  end;
 | 
						|
 | 
						|
begin
 | 
						|
  count:=0;
 | 
						|
  argc:=1;
 | 
						|
  argv:=nil;
 | 
						|
  argvlen:=0;
 | 
						|
  { load commandline from psp }
 | 
						|
  sysseg_move(psp_selector, 128, get_ds, longint(@doscmd), 128);
 | 
						|
  doscmd[length(doscmd)+1]:=#0;
 | 
						|
{$IfDef SYSTEM_DEBUG_STARTUP}
 | 
						|
  Writeln(stderr,'Dos command line is #',doscmd,'# size = ',length(doscmd));
 | 
						|
{$EndIf }
 | 
						|
  { create argv[0] }
 | 
						|
  argv0len:=strlen(dos_argv0);
 | 
						|
  allocarg(count,argv0len);
 | 
						|
  move(dos_argv0^,argv[count]^,argv0len);
 | 
						|
  inc(count);
 | 
						|
  { setup cmdline variable }
 | 
						|
  cmdline:=Getmem(argv0len+length(doscmd)+2);
 | 
						|
  move(dos_argv0^,cmdline^,argv0len);
 | 
						|
  cmdline[argv0len]:=' ';
 | 
						|
  inc(argv0len);
 | 
						|
  move(doscmd[1],cmdline[argv0len],length(doscmd));
 | 
						|
  cmdline[argv0len+length(doscmd)+1]:=#0;
 | 
						|
  { parse dos commandline }
 | 
						|
  pc:=@doscmd[1];
 | 
						|
  while pc^<>#0 do
 | 
						|
   begin
 | 
						|
     { skip leading spaces }
 | 
						|
     while pc^ in [#1..#32] do
 | 
						|
      inc(pc);
 | 
						|
     if pc^=#0 then
 | 
						|
      break;
 | 
						|
     { calc argument length }
 | 
						|
     quote:=' ';
 | 
						|
     argstart:=pc;
 | 
						|
     arglen:=0;
 | 
						|
     while (pc^<>#0) do
 | 
						|
      begin
 | 
						|
        case pc^ of
 | 
						|
          #1..#32 :
 | 
						|
            begin
 | 
						|
              if quote<>' ' then
 | 
						|
               inc(arglen)
 | 
						|
              else
 | 
						|
               break;
 | 
						|
            end;
 | 
						|
          '"' :
 | 
						|
            begin
 | 
						|
              if quote<>'''' then
 | 
						|
               begin
 | 
						|
                 if pchar(pc+1)^<>'"' then
 | 
						|
                  begin
 | 
						|
                    if quote='"' then
 | 
						|
                     quote:=' '
 | 
						|
                    else
 | 
						|
                     quote:='"';
 | 
						|
                  end
 | 
						|
                 else
 | 
						|
                  inc(pc);
 | 
						|
               end
 | 
						|
              else
 | 
						|
               inc(arglen);
 | 
						|
            end;
 | 
						|
          '''' :
 | 
						|
            begin
 | 
						|
              if quote<>'"' then
 | 
						|
               begin
 | 
						|
                 if pchar(pc+1)^<>'''' then
 | 
						|
                  begin
 | 
						|
                    if quote=''''  then
 | 
						|
                     quote:=' '
 | 
						|
                    else
 | 
						|
                     quote:='''';
 | 
						|
                  end
 | 
						|
                 else
 | 
						|
                  inc(pc);
 | 
						|
               end
 | 
						|
              else
 | 
						|
               inc(arglen);
 | 
						|
            end;
 | 
						|
          else
 | 
						|
            inc(arglen);
 | 
						|
        end;
 | 
						|
        inc(pc);
 | 
						|
      end;
 | 
						|
     { copy argument }
 | 
						|
     allocarg(count,arglen);
 | 
						|
     quote:=' ';
 | 
						|
     pc:=argstart;
 | 
						|
     arg:=argv[count];
 | 
						|
     while (pc^<>#0) do
 | 
						|
      begin
 | 
						|
        case pc^ of
 | 
						|
          #1..#32 :
 | 
						|
            begin
 | 
						|
              if quote<>' ' then
 | 
						|
               begin
 | 
						|
                 arg^:=pc^;
 | 
						|
                 inc(arg);
 | 
						|
               end
 | 
						|
              else
 | 
						|
               break;
 | 
						|
            end;
 | 
						|
          '"' :
 | 
						|
            begin
 | 
						|
              if quote<>'''' then
 | 
						|
               begin
 | 
						|
                 if pchar(pc+1)^<>'"' then
 | 
						|
                  begin
 | 
						|
                    if quote='"' then
 | 
						|
                     quote:=' '
 | 
						|
                    else
 | 
						|
                     quote:='"';
 | 
						|
                  end
 | 
						|
                 else
 | 
						|
                  inc(pc);
 | 
						|
               end
 | 
						|
              else
 | 
						|
               begin
 | 
						|
                 arg^:=pc^;
 | 
						|
                 inc(arg);
 | 
						|
               end;
 | 
						|
            end;
 | 
						|
          '''' :
 | 
						|
            begin
 | 
						|
              if quote<>'"' then
 | 
						|
               begin
 | 
						|
                 if pchar(pc+1)^<>'''' then
 | 
						|
                  begin
 | 
						|
                    if quote=''''  then
 | 
						|
                     quote:=' '
 | 
						|
                    else
 | 
						|
                     quote:='''';
 | 
						|
                  end
 | 
						|
                 else
 | 
						|
                  inc(pc);
 | 
						|
               end
 | 
						|
              else
 | 
						|
               begin
 | 
						|
                 arg^:=pc^;
 | 
						|
                 inc(arg);
 | 
						|
               end;
 | 
						|
            end;
 | 
						|
          else
 | 
						|
            begin
 | 
						|
              arg^:=pc^;
 | 
						|
              inc(arg);
 | 
						|
            end;
 | 
						|
        end;
 | 
						|
        inc(pc);
 | 
						|
      end;
 | 
						|
     arg^:=#0;
 | 
						|
 {$IfDef SYSTEM_DEBUG_STARTUP}
 | 
						|
     Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
 | 
						|
 {$EndIf SYSTEM_DEBUG_STARTUP}
 | 
						|
     inc(count);
 | 
						|
   end;
 | 
						|
  argc:=count;
 | 
						|
  { check for !proxy for long commandlines passed using environment }
 | 
						|
  hp:=envp;
 | 
						|
  useproxy:=false;
 | 
						|
  while assigned(hp^) do
 | 
						|
   begin
 | 
						|
     if (hp^[0]=' ') then
 | 
						|
      begin
 | 
						|
        proxy_s:=strpas(hp^);
 | 
						|
        if Copy(proxy_s,1,7)=' !proxy' then
 | 
						|
         begin
 | 
						|
           proxy_s[13]:=#0;
 | 
						|
           proxy_s[18]:=#0;
 | 
						|
           proxy_s[23]:=#0;
 | 
						|
           argv[2]:=@proxy_s[9];
 | 
						|
           argv[3]:=@proxy_s[14];
 | 
						|
           argv[4]:=@proxy_s[19];
 | 
						|
           useproxy:=true;
 | 
						|
           break;
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
     inc(hp);
 | 
						|
   end;
 | 
						|
  { check for !proxy for long commandlines passed using commandline }
 | 
						|
  if (not useproxy) and
 | 
						|
     (argc > 1) and (far_strlen(get_ds,longint(argv[1])) = 6)  then
 | 
						|
   begin
 | 
						|
     move(argv[1]^,proxy_s[1],6);
 | 
						|
     proxy_s[0] := #6;
 | 
						|
     if (proxy_s = '!proxy') then
 | 
						|
      useproxy:=true;
 | 
						|
   end;
 | 
						|
  { use proxy when found }
 | 
						|
  if useproxy then
 | 
						|
   begin
 | 
						|
     proxy_argc:=atohex(argv[2]);
 | 
						|
     proxy_seg:=atohex(argv[3]);
 | 
						|
     proxy_ofs:=atohex(argv[4]);
 | 
						|
{$IfDef SYSTEM_DEBUG_STARTUP}
 | 
						|
     Writeln(stderr,'proxy command line found');
 | 
						|
     writeln(stderr,'argc: ',proxy_argc,' seg: ',proxy_seg,' ofs: ',proxy_ofs);
 | 
						|
{$EndIf SYSTEM_DEBUG_STARTUP}
 | 
						|
     rm_argv:=SysGetmem(proxy_argc*sizeof(word));
 | 
						|
     sysseg_move(dos_selector,proxy_seg*16+proxy_ofs, get_ds,longint(rm_argv),proxy_argc*sizeof(word));
 | 
						|
     for count:=0 to proxy_argc - 1 do
 | 
						|
      begin
 | 
						|
        lin:=proxy_seg*16+rm_argv^[count];
 | 
						|
        arglen:=far_strlen(dos_selector,lin);
 | 
						|
        allocarg(count,arglen);
 | 
						|
        sysseg_move(dos_selector,lin,get_ds,longint(argv[count]),arglen+1);
 | 
						|
{$IfDef SYSTEM_DEBUG_STARTUP}
 | 
						|
        Writeln(stderr,'arg ',count,' #',rm_argv^[count],'#',arglen,'#',argv[count],'#');
 | 
						|
{$EndIf SYSTEM_DEBUG_STARTUP}
 | 
						|
    end;
 | 
						|
     SysFreemem(rm_argv);
 | 
						|
     argc:=proxy_argc;
 | 
						|
   end;
 | 
						|
  { create an nil entry }
 | 
						|
  allocarg(argc,0);
 | 
						|
  { free unused memory }
 | 
						|
  sysreallocmem(argv,(argc+1)*sizeof(pointer));
 | 
						|
end;
 | 
						|
 | 
						|
function strcopy(dest,source : pchar) : pchar;assembler;
 | 
						|
var
 | 
						|
  saveeax,saveesi,saveedi : longint;
 | 
						|
asm
 | 
						|
        movl    %edi,saveedi
 | 
						|
        movl    %esi,saveesi
 | 
						|
{$ifdef REGCALL}
 | 
						|
        movl    %eax,saveeax
 | 
						|
        movl    %edx,%edi
 | 
						|
{$else}
 | 
						|
        movl    source,%edi
 | 
						|
{$endif}
 | 
						|
        testl   %edi,%edi
 | 
						|
        jz      .LStrCopyDone
 | 
						|
        leal    3(%edi),%ecx
 | 
						|
        andl    $-4,%ecx
 | 
						|
        movl    %edi,%esi
 | 
						|
        subl    %edi,%ecx
 | 
						|
{$ifdef REGCALL}
 | 
						|
        movl    %eax,%edi
 | 
						|
{$else}
 | 
						|
        movl    dest,%edi
 | 
						|
{$endif}
 | 
						|
        jz      .LStrCopyAligned
 | 
						|
.LStrCopyAlignLoop:
 | 
						|
        movb    (%esi),%al
 | 
						|
        incl    %edi
 | 
						|
        incl    %esi
 | 
						|
        testb   %al,%al
 | 
						|
        movb    %al,-1(%edi)
 | 
						|
        jz      .LStrCopyDone
 | 
						|
        decl    %ecx
 | 
						|
        jnz     .LStrCopyAlignLoop
 | 
						|
        .balign  16
 | 
						|
.LStrCopyAligned:
 | 
						|
        movl    (%esi),%eax
 | 
						|
        movl    %eax,%edx
 | 
						|
        leal    0x0fefefeff(%eax),%ecx
 | 
						|
        notl    %edx
 | 
						|
        addl    $4,%esi
 | 
						|
        andl    %edx,%ecx
 | 
						|
        andl    $0x080808080,%ecx
 | 
						|
        jnz     .LStrCopyEndFound
 | 
						|
        movl    %eax,(%edi)
 | 
						|
        addl    $4,%edi
 | 
						|
        jmp     .LStrCopyAligned
 | 
						|
.LStrCopyEndFound:
 | 
						|
        testl   $0x0ff,%eax
 | 
						|
        jz      .LStrCopyByte
 | 
						|
        testl   $0x0ff00,%eax
 | 
						|
        jz      .LStrCopyWord
 | 
						|
        testl   $0x0ff0000,%eax
 | 
						|
        jz      .LStrCopy3Bytes
 | 
						|
        movl    %eax,(%edi)
 | 
						|
        jmp     .LStrCopyDone
 | 
						|
.LStrCopy3Bytes:
 | 
						|
        xorb     %dl,%dl
 | 
						|
        movw     %ax,(%edi)
 | 
						|
        movb     %dl,2(%edi)
 | 
						|
        jmp     .LStrCopyDone
 | 
						|
.LStrCopyWord:
 | 
						|
        movw    %ax,(%edi)
 | 
						|
        jmp     .LStrCopyDone
 | 
						|
.LStrCopyByte:
 | 
						|
        movb    %al,(%edi)
 | 
						|
.LStrCopyDone:
 | 
						|
{$ifdef REGCALL}
 | 
						|
        movl    saveeax,%eax
 | 
						|
{$else}
 | 
						|
        movl    dest,%eax
 | 
						|
{$endif}
 | 
						|
        movl    saveedi,%edi
 | 
						|
        movl    saveesi,%esi
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
var
 | 
						|
    env_selector:word; external name 'ENV_SELECTOR';
 | 
						|
    env_size:longint; external name 'ENV_SIZE';
 | 
						|
 | 
						|
procedure setup_environment;
 | 
						|
var env_count : longint;
 | 
						|
    dos_env,cp : pchar;
 | 
						|
begin
 | 
						|
  env_count:=0;
 | 
						|
  dos_env:=getmem(env_size);
 | 
						|
  sysseg_move(env_selector,$0, get_ds, longint(dos_env), env_size);
 | 
						|
  cp:=dos_env;
 | 
						|
  while cp ^ <> #0 do
 | 
						|
    begin
 | 
						|
    inc(env_count);
 | 
						|
    while (cp^ <> #0) do inc(longint(cp)); { skip to NUL }
 | 
						|
    inc(longint(cp)); { skip to next character }
 | 
						|
    end;
 | 
						|
  envp := sysgetmem((env_count+1) * sizeof(pchar));
 | 
						|
  if (envp = nil) then exit;
 | 
						|
  cp:=dos_env;
 | 
						|
  env_count:=0;
 | 
						|
  while cp^ <> #0 do
 | 
						|
   begin
 | 
						|
     envp[env_count] := sysgetmem(strlen(cp)+1);
 | 
						|
     strcopy(envp[env_count], cp);
 | 
						|
{$IfDef SYSTEM_DEBUG_STARTUP}
 | 
						|
     Writeln(stderr,'env ',env_count,' = "',envp[env_count],'"');
 | 
						|
{$EndIf SYSTEM_DEBUG_STARTUP}
 | 
						|
     inc(env_count);
 | 
						|
     while (cp^ <> #0) do
 | 
						|
      inc(longint(cp)); { skip to NUL }
 | 
						|
     inc(longint(cp)); { skip to next character }
 | 
						|
   end;
 | 
						|
  envp[env_count]:=nil;
 | 
						|
  longint(cp):=longint(cp)+3;
 | 
						|
  dos_argv0 := sysgetmem(strlen(cp)+1);
 | 
						|
  if (dos_argv0 = nil) then halt;
 | 
						|
  strcopy(dos_argv0, cp);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure syscopytodos(addr : sizeuint; len : longint);
 | 
						|
begin
 | 
						|
   if len > tb_size then
 | 
						|
     HandleError(217);
 | 
						|
   sysseg_move(get_ds,addr,dos_selector,tb,len);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure syscopyfromdos(addr : sizeuint; len : longint);
 | 
						|
begin
 | 
						|
   if len > tb_size then
 | 
						|
     HandleError(217);
 | 
						|
   sysseg_move(dos_selector,tb,get_ds,addr,len);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure sysrealintr(intnr : word;var regs : trealregs);
 | 
						|
begin
 | 
						|
   regs.realsp:=0;
 | 
						|
   regs.realss:=0;
 | 
						|
   asm
 | 
						|
      pushl %edi
 | 
						|
      pushl %ebx
 | 
						|
      pushw %fs
 | 
						|
      movw  intnr,%bx
 | 
						|
      xorl  %ecx,%ecx
 | 
						|
      movl  regs,%edi
 | 
						|
      movw  $0x300,%ax
 | 
						|
      int   $0x31
 | 
						|
      popw  %fs
 | 
						|
      popl %ebx
 | 
						|
      popl %edi
 | 
						|
   end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
 | 
						|
begin
 | 
						|
  asm
 | 
						|
        pushl %ebx
 | 
						|
        movl intaddr,%eax
 | 
						|
        movl (%eax),%edx
 | 
						|
        movw 4(%eax),%cx
 | 
						|
        movl $0x205,%eax
 | 
						|
        movb vector,%bl
 | 
						|
        int $0x31
 | 
						|
        popl %ebx
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
 | 
						|
begin
 | 
						|
  asm
 | 
						|
        pushl %ebx
 | 
						|
        movb    vector,%bl
 | 
						|
        movl    $0x204,%eax
 | 
						|
        int     $0x31
 | 
						|
        movl    intaddr,%eax
 | 
						|
        movl    %edx,(%eax)
 | 
						|
        movw    %cx,4(%eax)
 | 
						|
        popl %ebx
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                         System Dependent Exit code
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
procedure ___exit(exitcode:longint);cdecl;external name '___exit';
 | 
						|
 | 
						|
 | 
						|
Procedure system_exit;
 | 
						|
var
 | 
						|
  h : byte;
 | 
						|
begin
 | 
						|
  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;
 | 
						|
  { halt is not allways called !! }
 | 
						|
  { not on normal exit !! PM }
 | 
						|
  set_pm_interrupt($00,old_int00);
 | 
						|
{$ifndef EXCEPTIONS_IN_SYSTEM}
 | 
						|
  set_pm_interrupt($75,old_int75);
 | 
						|
{$endif EXCEPTIONS_IN_SYSTEM}
 | 
						|
  ___exit(exitcode);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure new_int00;
 | 
						|
begin
 | 
						|
  HandleError(200);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
{$ifndef EXCEPTIONS_IN_SYSTEM}
 | 
						|
procedure new_int75;
 | 
						|
begin
 | 
						|
  asm
 | 
						|
        xorl    %eax,%eax
 | 
						|
        outb    %al,$0x0f0
 | 
						|
        movb    $0x20,%al
 | 
						|
        outb    %al,$0x0a0
 | 
						|
        outb    %al,$0x020
 | 
						|
  end;
 | 
						|
  HandleError(200);
 | 
						|
end;
 | 
						|
{$endif EXCEPTIONS_IN_SYSTEM}
 | 
						|
 | 
						|
 | 
						|
var
 | 
						|
  __stkbottom : pointer;//###########external name '__stkbottom';
 | 
						|
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                              ParamStr/Randomize
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
function paramcount : longint;
 | 
						|
begin
 | 
						|
  paramcount := argc - 1;
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
function paramstr(l : longint) : string;
 | 
						|
begin
 | 
						|
  if (l>=0) and (l+1<=argc) then
 | 
						|
   paramstr:=strpas(argv[l])
 | 
						|
  else
 | 
						|
   paramstr:='';
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
procedure randomize;
 | 
						|
var
 | 
						|
  hl   : longint;
 | 
						|
  regs : trealregs;
 | 
						|
begin
 | 
						|
  regs.realeax:=$2c00;
 | 
						|
  sysrealintr($21,regs);
 | 
						|
  hl:=lo(regs.realedx);
 | 
						|
  randseed:=hl*$10000+ lo(regs.realecx);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
{ include standard heap management }
 | 
						|
 { include heap.inc}
 | 
						|
 | 
						|
 | 
						|
(*
 | 
						|
{*****************************************************************************
 | 
						|
                           UnTyped File Handling
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
{$i file.inc}
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                           Typed File Handling
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
{$i typefile.inc}
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                           Text File Handling
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
{$i text.inc}
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                           Generic Handling
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
{$ifdef TEST_GENERIC}
 | 
						|
{$i generic.inc}
 | 
						|
{$endif TEST_GENERIC}
 | 
						|
*)
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                         SystemUnit Initialization
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
function CheckLFN:boolean;
 | 
						|
var
 | 
						|
  regs     : TRealRegs;
 | 
						|
  RootName : pchar;
 | 
						|
begin
 | 
						|
{ Check LFN API on drive c:\ }
 | 
						|
  RootName:='C:\';
 | 
						|
  syscopytodos(longint(RootName),strlen(RootName)+1);
 | 
						|
{ Call 'Get Volume Information' ($71A0) }
 | 
						|
  regs.realeax:=$71a0;
 | 
						|
  regs.reales:=tb_segment;
 | 
						|
  regs.realedi:=tb_offset;
 | 
						|
  regs.realecx:=32;
 | 
						|
  regs.realds:=tb_segment;
 | 
						|
  regs.realedx:=tb_offset;
 | 
						|
  regs.realflags:=carryflag;
 | 
						|
  sysrealintr($21,regs);
 | 
						|
{ If carryflag=0 and LFN API bit in ebx is set then use Long file names }
 | 
						|
  CheckLFN:=(regs.realflags and carryflag=0) and (regs.realebx and $4000=$4000);
 | 
						|
end;
 | 
						|
 | 
						|
{$ifdef  EXCEPTIONS_IN_SYSTEM}
 | 
						|
{$define IN_SYSTEM}
 | 
						|
{$i dpmiexcp.pp}
 | 
						|
{$endif  EXCEPTIONS_IN_SYSTEM}
 | 
						|
 | 
						|
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 := 1;
 | 
						|
end;
 | 
						|
 | 
						|
function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
 | 
						|
begin
 | 
						|
  result := stklen;
 | 
						|
end;
 | 
						|
 | 
						|
var
 | 
						|
  temp_int : tseginfo;
 | 
						|
Begin
 | 
						|
  alloc_tb;
 | 
						|
  StackLength := InitialStkLen;
 | 
						|
  StackBottom := __stkbottom;
 | 
						|
  { 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;
 | 
						|
{ save old int 0 and 75 }
 | 
						|
  get_pm_interrupt($00,old_int00);
 | 
						|
  get_pm_interrupt($75,old_int75);
 | 
						|
  temp_int.segment:=get_cs;
 | 
						|
  temp_int.offset:=@new_int00;
 | 
						|
  set_pm_interrupt($00,temp_int);
 | 
						|
{$ifndef EXCEPTIONS_IN_SYSTEM}
 | 
						|
  temp_int.offset:=@new_int75;
 | 
						|
  set_pm_interrupt($75,temp_int);
 | 
						|
{$endif EXCEPTIONS_IN_SYSTEM}
 | 
						|
{ Setup heap }
 | 
						|
  InitHeap;
 | 
						|
  SysInitExceptions;
 | 
						|
  initunicodestringmanager;
 | 
						|
{ Setup stdin, stdout and stderr }
 | 
						|
  SysInitStdIO;
 | 
						|
{ Setup environment and arguments }
 | 
						|
  Setup_Environment;
 | 
						|
  Setup_Arguments;
 | 
						|
{ Use LFNSupport LFN }
 | 
						|
  LFNSupport:=CheckLFN;
 | 
						|
  if LFNSupport then
 | 
						|
   begin
 | 
						|
    FileNameCasePreserving:=true;
 | 
						|
    AllFilesMask := '*';
 | 
						|
   end
 | 
						|
  else
 | 
						|
   AllFilesMask := '*.*';
 | 
						|
 | 
						|
{ Reset IO Error }
 | 
						|
  InOutRes:=0;
 | 
						|
  ThreadID := 1;
 | 
						|
{$ifdef  EXCEPTIONS_IN_SYSTEM}
 | 
						|
  InitDPMIExcp;
 | 
						|
  InstallDefaultHandlers;
 | 
						|
{$endif  EXCEPTIONS_IN_SYSTEM}
 | 
						|
End.
 |