program CrLf;

{
 Konvertiert Unix-Textdateien zu DOS und umgekehrt.
 Aufruf:

    crlf [Modus] [Eingabedatei] [Ausgabedatei]

 Dabei ist Modus entweder 'd', um ins DOS-Format zu konvertieren, oder 'u'
 für die andere Richtung.

 Version 0.1

 Copyright (c) 10/99 by Sebastian Koppehel, <basti@bastisoft.de>
 }

const
   BufLen   = 1024;
   BufFull  = 1;
   BufEmpty = 2;

type
   fStream = record
		InBuf	 : Array[1..BufLen] of Char;
		OutBuf	 : Array[1..BufLen] of Char;
		NextIn	 : LongInt;
		InAvail	 : LongInt;
		NextOut	 : LongInt;
		OutAvail : LongInt;
	     end;

function InsertCr(var s	: fStream) : LongInt;
var
   Full	: Boolean;
   c	: Char;
begin
   Full := s.OutAvail = 0;
   while (s.InAvail > 0) and not Full do
   begin
      c := s.InBuf[s.NextIn];
      if c = #10 then
      begin
	 if s.OutAvail >= 2 then
	 begin
	    s.OutBuf[s.NextOut] := #13;
	    s.OutBuf[s.NextOut + 1] := #10;
	    Inc(s.NextOut,2);
	    Dec(s.OutAvail,2);
	    Inc(s.NextIn);
	    Dec(s.InAvail);
	 end
	 else Full := True;
      end
      else
      begin
	 s.OutBuf[s.NextOut] := c;
	 Inc(s.NextOut);
	 Dec(s.OutAvail);
	 Inc(s.NextIn);
	 Dec(s.InAvail);
      end;
      Full := Full or (s.OutAvail < 1);
   end;
   if Full then InsertCr := BufFull
   else InsertCr := BufEmpty;
end;

function DeleteCr(var s	: fStream) : LongInt;
begin
   while (s.InAvail > 0) and (s.OutAvail > 0) do
   begin
      if s.InBuf[s.NextIn] <> #13 then
      begin
	 s.OutBuf[s.NextOut] := s.InBuf[s.NextIn];
	 Inc(s.NextOut);
	 Dec(s.OutAvail);
      end;
      Inc(s.NextIn);
      Dec(s.InAvail);
   end;
   if s.InAvail = 0 then DeleteCr := BufEmpty
   else DeleteCr := BufFull;
end;

var
   Mode	     : (ToDos,ToUnix,None);
   Result    : LongInt;
   InF, OutF : File;
   s	     : fStream;

begin
   if ParamCount < 3 then
   begin
      Writeln('Nicht genügend Parameter.');
      Halt;
   end;
   if ParamStr(1) = 'd' then
      Mode := ToDos
   else if ParamStr(1) = 'u' then
      Mode := ToUnix
   else
   begin
      Writeln('Unbekannter Modus.');
      Mode := None;
   end;
   if Mode <> None then
   begin
      Assign(InF,ParamStr(2));
      Reset(InF,1);
      Assign(OutF,ParamStr(3));
      Rewrite(OutF,1);
      while not eof(InF) do
      begin
	 BlockRead(InF,s.InBuf,BufLen,s.InAvail);
	 s.NextIn := 1;
	 repeat
	    s.NextOut := 1;
	    s.OutAvail := BufLen;
	    if Mode = ToDos then Result := InsertCr(s)
	    else Result := DeleteCr(s);
	    BlockWrite(OutF,s.OutBuf,BufLen - s.OutAvail);
	 until Result = BufEmpty;
      end;
      Close(InF);
      Close(OutF);
   end;
end.
