home *** CD-ROM | disk | FTP | other *** search
- {
- Fast driver for backwards reading... Aha!
- This is the way to do it.
-
- Below you will find the source of a "tail" program.
- I wrote it because I needed to check the status of some log files,
- and I didn't want to go through the entire file every time, as the
- files could grow quite large.
-
- It is currently limited to 255 chars per line, but that
- can easily be fixed (see the Limit const).
-
- Although it's not an exact solution to your problem, it will show you
- how to do "backwards" reading.
- }
-
- PROGRAM Tail;
- {
- Shows the tailing lines of a text file.
-
- Syntax: TAIL [d:\path]filespec.ext [-<lines>]
- Default number of lines is 10.
-
- "TAIL filename -20" will show the 20 last lines
-
- Written by Lars Fosdal, 1993
- Released to the Public Domain by Lars Fosdal, 1993
- }
-
- USES
- DOS, Objects, Strings;
-
- CONST
- MaxBufSize = 32000;
- TYPE
- pBuffer = ^TBuffer;
- TBuffer = ARRAY[0..MaxBufSize-1] OF Char;
-
- pRawStrCollection = ^TRawStrCollection;
- TRawStrCollection = OBJECT(TCollection)
- PROCEDURE FreeItem(Item:Pointer); VIRTUAL;
- END;
-
- PROCEDURE TRawStrCollection.FreeItem(Item:Pointer);
- BEGIN
- IF Item<>nil
- THEN StrDispose(pChar(Item));
- END; {PROC TRawStrCollection.FreeItem}
-
- FUNCTION ShowTail(FileName:String; n:Integer):Integer;
- PROCEDURE DumpLine(p:pChar); FAR;
- BEGIN
- IF p^=#255
- THEN Writeln
- ELSE Writeln(p);
- END;
- CONST
- Limit = 255;
- VAR
- lines : pRawStrCollection;
- fm : Byte;
- f : File;
- fs,fp : LongInt;
- MaxRead : Word;
- Buf : pBuffer;
- lc,ix,ex : Integer;
- sp : ARRAY[0..Limit] OF Char;
- BEGIN
- lines:=nil;
- fm:=FileMode;
- FileMode:=$40; {Read-only, deny none}
- Assign(f, FileName);
- Reset(f, 1);
- lc:=IOResult;
- IF lc=0
- THEN BEGIN
- New(Buf);
-
- fs:=FileSize(f); {First, let's find out how much to read}
- fp:=fs-MaxBufSize;
- IF fp<0
- THEN fp:=0;
-
- Seek(f,fp); {Then, read it}
- BlockRead(f, Buf^, MaxBufSize, MaxRead);
- Close(f);
-
- IF MaxRead>0
- THEN BEGIN
- New(Lines, Init(n,10));
- ix:=MaxRead-1;
-
- IF Buf^[ix]=^J THEN Dec(ix);
- IF (ix>0) and (Buf^[ix]=^M) THEN Dec(ix); {Skip trailing line break}
-
- WHILE (lc<n) and (ix>0)
- DO BEGIN
- ex:=ix;
- FillChar(sp, SizeOf(sp), 0);
-
- WHILE (ix>0) and not (Buf^[ix] =^J)
- DO Dec(ix);
-
- IF ex-ix<=Limit {If no break was found within limit, it's no txt file}
- THEN BEGIN
- IF ix=ex
- THEN sp[0]:=#255 {Pad empty lines to avoid zero-length pchar}
- ELSE StrLCopy(sp, @Buf^[ix+1], ex-ix);
- Inc(lc);
-
- Lines^.AtInsert(0, StrNew(sp));
-
- Dec(ix);
- WHILE (ix>0) and (Buf^[ix] =^M)
- DO Dec(ix);
- END
- ELSE BEGIN
- Writeln('"',FileName,'" doesn''t seem to be a text file');
- ix:=-1;
- END;
-
- END; {lc<n and ix>0}
- END {Maxread>0}
- ELSE Lines:=nil;
- Dispose(Buf);
- END
- ELSE lc:=-lc;
-
- IF Lines<>nil
- THEN BEGIN
- Lines^.ForEach(@DumpLine);
- Dispose(Lines, Done);
- END;
-
- ShowTail:=lc;
- FileMode:=fm;
- END; {FUNC ShowTail}
-
- TYPE
- CharSet = Set of Char;
-
- FUNCTION StripAll(CONST Exclude:CharSet; S:String):String;
- VAR
- ix : Integer;
- BEGIN
- ix:=Length(S);
- WHILE ix>0
- DO BEGIN
- IF S[ix] in Exclude
- THEN Delete(S, ix, 1);
- Dec(ix);
- END;
- StripAll:=S;
- END; {FUNC StripAll}
-
- VAR
- r : Integer;
- l : Integer;
- e : Integer;
- BEGIN
- IF (ParamCount<1) or (ParamCount>2)
- THEN BEGIN
- Writeln('TAIL v.1.0 - PD 1993 Lars Fosdal');
- Writeln(' TAIL [d:\path]filename.ext [-n]');
- Writeln(' Default is 10 lines');
- END
- ELSE BEGIN
- IF ParamCount=2
- THEN BEGIN
- Val(StripAll(['/','-'], ParamStr(2)), l, e);
- IF e<>0
- THEN l:=10
- END
- ELSE l:=10;
-
- r:=ShowTail(ParamStr(1), l);
- IF r<0
- THEN BEGIN
- Writeln('Couldn''t open "',ParamStr(1),'"! (Error ', -r,')');
- Halt(Word(-r));
- END;
- END;
- END.