{Ý_______________________________________________________Ý}
{Ý                                                       Ý}
{Ý      Virtual Pascal Examples. Version 2.1.            Ý}
{Ý      Grep filter for VP IDE                           Ý}
{Ý      -------------------------------------------------Ý}
{Ý      Copyright (C) 2000 vpascal.com                   Ý}
{Ý                                                       Ý}
{_________________________________________________________}

program GrepMsg;

{ This utility is used in the IDE's Tools menu when executing GREP.

  It reads from standard input (which it expects to contain the output
  from GREP), and writes messages to standard output as a result.

  The output written is in a format the VP IDE can parse to enable
  navigating source files.
}

{$X+,Delphi+}

uses
  VpSysLow, Dos;

const
  StandardHeader = 'VPMSG!#1#2#3';

var
  InputBuffer: array[0..2095] of Char;
  OutputBuffer: array[0..4095] of Char;
  StdIn: Text;
  StdOut: Text;

procedure WriteHeader;
begin
  Write( StdOut, StandardHeader );
end;

procedure WriteFileName( const _FileName: String );
begin
  Write( StdOut, #0, _FileName, #0 );
end;

procedure WriteMessage( const _Message: String );
begin
  Write( StdOut, #2, _Message, #0 );
end;

procedure WritePosition( _Line, _Col: Longint; const _Message: String);

  procedure WriteLong( _Data: Longint );
  var
    i: Integer;
  begin
    for i := 1 to 4 do
      begin
        Write( StdOut, chr(_Data and $FF) );
        _Data := _Data shr 8;
      end;
  end;

begin
  Write( StdOut, #1 );
  WriteLong( _Line );
  WriteLong( _Col );
  Write( StdOut, _Message );
  Write( StdOut, #0 );
end;

procedure WriteEnd;
begin
  Write( StdOut, #26 );
  Close(StdOut);
end;

procedure Trim( var _S: String );
var
  i: Integer;
begin
  i := 1;
  while _S[i] in ['0'..'9'] do
    inc(i);
  while _S[i] = ' ' do
    inc(i);
  Delete(_S, 1, i-1);
end;

procedure Initialise;
begin
  TextModeRead := Open_Access_ReadOnly OR open_share_DenyNone;
  Assign(StdIn, '');
  Reset(StdIn);
  SetTextBuf(StdIn, InputBuffer);

  TextModeReadWrite := Open_Access_ReadWrite OR open_share_DenyNone;
  Assign(StdOut, '');
  rewrite(StdOut);
  SetTextBuf(StdOut, OutputBuffer);
end;

procedure ProcessMessages;
var
  Column: Longint;
  LineNumber, Error: Longint;
  s, Line: String;
  ch: Char;

begin
  while not Eof(StdIn) do
    begin
      ReadLn(StdIn, Line);
      if Line <> '' then
        begin
{$IFDEF OS2} // --- OS/2 version ---
          s := Copy(Line, 1, pos(' ',Line)-1);
          WriteFileName( s );
          Delete(Line, 1, Length(s)+1);
          // Determine line number
          s := copy(Line, 1, pos(' ',Line)-1);
          Val(s, LineNumber, Error);
          if Error <> 0 then
            begin
              LineNumber := -1;
              Column := 0;
            end
          else
            begin
              Delete(Line, 1, Length(s)+1);
              // Determine column number
              s := copy(Line, 1, pos(':',Line)-1);
              Val(s, Column, Error);
              if Error <> 0 then
                Column := -1
              else
                Delete(Line, 1, Length(s)+1);
            end;
          // Prepare to print line
          Trim(Line);
          WritePosition(LineNumber, Column, Line);

{$ELSE}   // --- Windows version ---

          if Copy(Line, 1, 5) = 'File ' then
            WriteFileName( Copy(Line, 6, Length(Line) - 6) )
          else
            if (Copy(Line, 1, 6) = 'Error:') or (copy(Line,1,5) = 'grep:') then
              WriteMessage( Line )
            else
            begin
              // Determine line number
              Val(Copy(Line, 1, Pos(' ', Line) - 1), LineNumber, Error);
              if Error = 0 then
                begin
                  Trim(Line);
                  WritePosition(LineNumber, -1, Line);
                end;
            end;
{$ENDIF}
        end;
    end;
end;

begin
  Initialise;
  WriteHeader;
  ProcessMessages;
  WriteEnd;
end.

