home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaDemoCD1.iso / DEMOS / GADGET22.LHA / AmigaGadget22 / jgrep-Source / jgrep.mod < prev    next >
Encoding:
Text File  |  1995-11-27  |  5.9 KB  |  272 lines

  1. (***************************************************************************
  2.  
  3.     MODUL
  4.       jgrep.mod
  5.  
  6.     DESCRIPTION
  7.       sucht in Textdateien nach einem Muster und gibt alle Zeilen aus, in
  8.       denen es enthalten ist.
  9.       optionale Flags:
  10.          SLOW: Anstelle des Boyer-Moore Algorithmus' wird die direkte Suche
  11.                benutzt - interessant sicherlich nur mit dem DEBUG-Flag.
  12.          DEBUG: Es werden einige zusätzliche Informationen, wie die Anzahl
  13.                 der durchgeführten Vergleiche ausgegeben.
  14.  
  15.     NOTES
  16.       Der Boyer-Moore Algorithmus ist optimierbar, indem das skip-Array
  17.       nicht für jede Zeile neu berechnet wird, sondern einmal am Anfang.
  18.       Ich habe es hier nur einmal so realisiert, um den Algorithmus
  19.       geschlossen in sich zu halten.
  20.  
  21.     BUGS
  22.  
  23.     TODO
  24.  
  25.     EXAMPLES
  26.  
  27.     SEE ALSO
  28.  
  29.     INDEX
  30.  
  31.     HISTORY
  32.       11-11-95 Roland (rj,-) Jesse  created
  33.  
  34. ***************************************************************************)
  35.  
  36. <*STANDARD-*>               (* necessary for assignable cleanup procedure *)
  37.  
  38. MODULE jgrep;
  39.  
  40. IMPORT
  41.    jgrepRev,
  42.    Errors, Kernel,
  43.    d := Dos,
  44.    e := Exec,
  45.    f := Files,
  46.    Out,
  47.    S := SYSTEM,
  48.    Strings;
  49.  
  50. TYPE
  51.    String = ARRAY 256 OF CHAR;
  52.    IntArray = ARRAY 256 OF INTEGER;
  53.  
  54. CONST
  55.    template = "PATTERN/A,FILE/A,S=SLOW/K/S,D=DEBUG/K/S";
  56.    optPattern = 0;
  57.    optFile = 1;
  58.    optSlow = 2;
  59.    optDebug = 3;
  60.    optCount = 4;                 (* Anzahl der Parameter *)
  61.  
  62.    CR = 0DX; LF = 0AX;
  63.  
  64. VAR
  65.    rdArgs : d.RDArgsPtr;
  66.    file  : e.LSTRPTR;
  67.    pattern : e.LSTRPTR;
  68.    line : String;
  69.    succ : BOOLEAN;               (* search successful ? *)
  70.    debug : BOOLEAN;              (* debug-mode ? *)
  71.    slow : BOOLEAN;               (* direkte Suche verwenden ? *)
  72.    fhandle : f.File;             (* File-Handle für die Datei *)
  73.    r : f.Rider;
  74.    ch : CHAR;
  75.    compares, i : INTEGER;
  76.  
  77.  
  78. (* Remove all the allocated stuff *)
  79. PROCEDURE* Cleanup (VAR rc : LONGINT);
  80. BEGIN
  81.    IF fhandle # NIL THEN f.Close (fhandle) END;
  82.    IF rdArgs # NIL THEN d.FreeArgs (rdArgs) END
  83. END Cleanup;
  84.  
  85.  
  86. PROCEDURE Init;
  87. BEGIN
  88.    (* Errors.Init; *)
  89.    Kernel.SetCleanup (Cleanup);
  90.    rdArgs := NIL; slow := FALSE; debug := FALSE; compares := 0;
  91.    COPY ("", line)
  92. END Init;
  93.  
  94.  
  95. PROCEDURE GetArgs;
  96. VAR
  97.    argArray : ARRAY optCount OF S.LONGWORD;
  98. BEGIN
  99.    rdArgs := d.OldReadArgs (template, argArray, NIL);
  100.    IF rdArgs # NIL THEN
  101.       (*
  102.        * Wegen dem /A steht in beiden auf jeden Fall etwas.
  103.        *)
  104.       pattern := S.VAL (e.LSTRPTR, argArray [optPattern]);
  105.       file := S.VAL (e.LSTRPTR, argArray [optFile]);
  106.       slow := S.VAL (BOOLEAN, argArray [optSlow]);
  107.       debug := S.VAL (BOOLEAN, argArray [optDebug]);
  108.    ELSE
  109.       ASSERT (d.PrintFault (d.IoErr(), "ReadArgs"));
  110.       HALT (d.error)
  111.    END
  112. END GetArgs;
  113.  
  114.  
  115. (* direkte Suche, optimierte Version (Abbruch bei erstem Mismatch) *)
  116. PROCEDURE SlowSearch () : BOOLEAN;
  117. VAR
  118.    i, j, M, N : INTEGER;
  119.    m, z : String;
  120.  
  121. BEGIN (* SlowSearch *)
  122.    COPY (line, z);
  123.    COPY (pattern^, m);
  124.    M := Strings.Length (m); N := Strings.Length (z);
  125.  
  126.    (* neue Fassung: *)
  127.    i := 0; j := 0;
  128.    REPEAT
  129.       IF z[i] = m[j] THEN
  130.          INC (i); INC (j); INC (compares);
  131.       ELSE
  132.          i := i - j + 1;
  133.          j := 0;
  134.          INC (compares);
  135.       END;
  136.    UNTIL (j = M) OR (i >= N);
  137.  
  138.    IF j = M THEN
  139.       RETURN TRUE
  140.    ELSE
  141.       RETURN FALSE
  142.    END
  143. END SlowSearch;
  144.  
  145.  
  146. (* f. BMsearch *)
  147. PROCEDURE initskip ( VAR skip : IntArray );
  148. VAR
  149.  j, t, M : INTEGER;
  150.  m : String;
  151.  
  152. BEGIN
  153.    COPY (pattern^, m);
  154.    M := Strings.Length (m);
  155.    FOR j := 0 TO 255 DO
  156.       skip[j] := M
  157.    END;
  158.  
  159.    FOR j := 0 TO M-1 DO
  160.       t := ORD (m[j]);
  161.       skip[t] := M-j-1
  162.    END
  163. END initskip;
  164.  
  165.  
  166. PROCEDURE BMsearch () : BOOLEAN;
  167. VAR
  168.    i, j, t, M, N : INTEGER;
  169.    skip : IntArray;
  170.    m, z : String;
  171.  
  172. BEGIN
  173.    COPY (line, z);
  174.    COPY (pattern^, m);
  175.    M := Strings.Length (m); N := Strings.Length (z);
  176.  
  177.    initskip (skip);
  178.  
  179.    i := M-1; j := M-1;
  180.    REPEAT
  181.       IF z[i] = m[j] THEN
  182.          INC (compares);
  183.          DEC (i);
  184.          DEC (j);
  185.       ELSE (* Mismatch wegen z[i] => i erhöhen, j ans Ende des Musters *)
  186.          INC (compares);
  187.          t := skip[ ORD (z[i]) ];
  188.          IF M-j > t THEN
  189.             i := i + M-j
  190.          ELSE
  191.             i := i + t
  192.          END;
  193.          j := M-1
  194.       END
  195.    UNTIL (j < 0) OR (i >= N);
  196.  
  197.    IF i >= N THEN
  198.       RETURN FALSE
  199.    ELSE
  200.       RETURN TRUE
  201.    END
  202. END BMsearch;
  203.  
  204.  
  205. PROCEDURE ClearLine;
  206. VAR
  207.    i : INTEGER;
  208. BEGIN (* ClearLine *)
  209.    FOR i := 0 TO 255 DO
  210.       line[i] := ""
  211.    END
  212. END ClearLine;
  213.  
  214.  
  215. <*$CopyArrays-*>
  216. BEGIN (* grep *)
  217.    Init ();
  218.    GetArgs ();
  219.  
  220.    (* open file *)
  221.    fhandle := f.Old (file^);
  222.    IF fhandle # NIL THEN
  223.       f.Set (r, fhandle, 0);
  224.  
  225.       WHILE ~r.eof DO
  226.          f.Read (r, ch);
  227.          LOOP
  228.             ClearLine;
  229.             (* read in next line *)
  230.             i := 0;
  231.             line[i] := ch;
  232.             WHILE ch # LF DO
  233.                INC (i);
  234.                f.Read (r, ch);
  235.                line[i] := ch;
  236.             END;
  237.  
  238.             (* search for the pattern *)
  239.             IF slow = TRUE THEN
  240.                succ := SlowSearch ()
  241.             ELSE
  242.                succ := BMsearch ()
  243.             END;
  244.  
  245.             (* print the line when found the pattern *)
  246.             IF succ = TRUE THEN
  247.                IF debug = TRUE THEN
  248.                   IF slow = TRUE THEN Out.String ("dS: ");
  249.                                  ELSE Out.String ("BM: ");
  250.                   END;
  251.                END;
  252.                Out.String (line)
  253.             END;
  254.          f.Read (r, ch);
  255.          IF r.eof THEN EXIT END
  256.          END; (* of LOOP *)
  257.       END; (* WHILE ~r.eof *)
  258.  
  259.       IF debug = TRUE THEN
  260.          IF slow = TRUE THEN Out.String ("dS, ")
  261.                         ELSE Out.String ("BM, ")
  262.          END;
  263.          Out.String ("Anz. Vergleiche: "); Out.Int (compares, 3); Out.Ln ()
  264.       END;
  265.       f.Close (fhandle); fhandle := NIL;
  266.    ELSE
  267.       Out.String ("Could not open "); Out.String (file^); Out.Ln ()
  268.    END;
  269.    IF debug = TRUE THEN Out.String ("done\n") END
  270. END jgrep.
  271.  
  272.