program Excepts;

uses
  SysUtils, VpSysLow, Linux;

var
  I, X: LongInt;
  F: Extended;
  P: PChar;

begin
  I := 0;
  F := 0.0;
  P := Pointer($12345678);

  WriteLn('First we test a complex series of language exceptions (raise):');
  WriteLn('--------------------------------------------------------------');
  WriteLn('Begin...');

  X := 0;

  try
    WriteLn('Outer try block...');
    X := X + 1;

    try
      WriteLn('Middle try block...');
      X := X + 1;

      try
        WriteLn('Inner try block...');
        X := X + 1;

        raise Exception.Create('Exception');
        X := X - 1;

      except
        WriteLn('Inner except block...');

        try
          WriteLn('Even more inner try block...');
          X := X + 1;
          raise Exception.Create('Exception');
          X := X - 1;
        except
          WriteLn('Even more inner exception handled.');
          X := X + 1;
        end;

        WriteLn('Re-raising exception from inner block.');

        X := X + 1;
        raise;
        X := X - 1;
      end;

    finally
      WriteLn('Middle finally block...');
      X := X + 1;
    end;

  except
    WriteLn('Outer except block...');
    X := X + 1;
  end;

  WriteLn('End...');

  if X = 8 then WriteLn('Okay.') else
  begin
    WriteLn('Error! (X is ', X, ', should be 8.)');
    Halt;
  end;

  WriteLn;
  WriteLn('Next we test a complex series of signal exceptions (SIGSEGV):');
  WriteLn('-------------------------------------------------------------');
  WriteLn('Begin...');

  X := 0;

  try
    WriteLn('Outer try block...');
    X := X + 1;

    try
      WriteLn('Middle try block...');
      X := X + 1;

        try
          WriteLn('Inner try block...');
          X := X + 1;

          P^ := '?';
          X := X - 1;

        except
          WriteLn('Inner except block...');

          try
            WriteLn('Even more inner try block...');
            X := X + 1;
            P^ := '?';
            X := X - 1;
          except
            WriteLn('Even more inner exception handled.');
            X := X + 1;
          end;

          WriteLn('Re-raising exception from inner block.');

          X := X + 1;
          raise;
          X := X - 1;
        end;

    finally
      WriteLn('Middle finally block...');
      X := X + 1;
    end;

  except
    WriteLn('Outer except block...');
    X := X + 1;
  end;

  WriteLn('End...');

  if X = 8 then WriteLn('Okay.') else
  begin
    WriteLn('Error! (X is ', X, ', should be 8.)');
    Halt;
  end;

  WriteLn;
  WriteLn('Finally we test some individual exceptions:');
  WriteLn('-------------------------------------------');
  WriteLn('Begin...');

  try
    WriteLn('Trying 1 div 0...');
    WriteLn(1 div I);
  except
    on E: Exception do
    begin
      WriteLn('Error: ', E.Message);
    end;
  end;

  WriteLn;

  try
    WriteLn('Trying 1.0 / 0.0...');
    WriteLn(1.0 / F);
  except
    on E: Exception do
    begin
      WriteLn('Error: ', E.Message);
    end;
  end;

  WriteLn;

  try
    WriteLn('Trying read access at $12345678...');
    WriteLn(P^);
  except
    on E: Exception do
    begin
      WriteLn('Error: ', E.Message);
    end;
  end;

  WriteLn;

  try
    WriteLn('Trying write access at $12345678...');
    P^ := '?';
  except
    on E: Exception do
    begin
      WriteLn('Error: ', E.Message);
    end;
  end;

  WriteLn;

  try
    WriteLn('Trying signal SIGUSR2...');
    LnxKill(LnxGetPid, SIGUSR2);
  except
    on E: Exception do
    begin
      WriteLn('Error: ', E.Message);
    end;
  end;

  try
    WriteLn('Trying Ctrl-C... (please press Ctrl-C)');
    ReadLn;
  except
    on E: Exception do
    begin
      WriteLn('Error: ', E.Message);
    end;
  end;

  WriteLn('End...');
  WriteLn;
  WriteLn('Everything seemed to work as designed. :-)');
end.

