packages feed

language-Modula2-0.1: examples/Modula-2_Libraries/andrea-m2/applications/fst/search/search.mod

MODULE Search;

(*
 Search the file given by argument 1
 for any line which contains all of the strings defined by arguments 2,3,...
*)
(* John Andrea, June.27/92 *)
(* This code may be freely distributed, it may not be sold *)

FROM Break IMPORT EnableBreak;
FROM System IMPORT GetArg;
FROM InOut IMPORT Write, WriteString, WriteLn, RedirectInput, Read, WriteCard, Done;
FROM ASCII IMPORT EOL, EOF;

CONST
  max_size = 30;
  max_args = 11;
  max_line = 133;

VAR
  i       :CARDINAL;

  n_args  :CARDINAL;
  arg     :ARRAY [1..max_args] OF ARRAY [1..max_size] OF CHAR;
  size    :ARRAY [1..max_args] OF CARDINAL;

  line    :ARRAY [1..max_line] OF CHAR;
  len     :CARDINAL;

  eof     :BOOLEAN;

  (* ------------------------------------------ *)
  PROCEDURE ReadLine;
  VAR
    c :CHAR;
  BEGIN

    Read( c );

    IF c = EOF THEN
      eof := TRUE;
    ELSE

      len := 1;

      WHILE ( len < max_line ) & ( c # EOL ) & ( c # EOF ) DO
        line[len] := c;
        Read( c );
        len := len + 1;
      END;

      IF len <= max_line THEN
       line[len] := 0C;
      ELSE
       (* finish reading this line, beacuse its too big to fit into the buffer *)
       Read( c );
       WHILE c # EOL DO
         Read( c );
       END;
      END;

      len := len - 1;

    END;

  END ReadLine;

    (* -------------------------------------------------------- *)
    PROCEDURE Contains( pattern :ARRAY OF CHAR; len_p :CARDINAL ) :BOOLEAN;
    VAR
       s, p :CARDINAL;
       done, found :BOOLEAN;
    BEGIN

       IF ( len_p = 0 ) OR ( len_p > len ) THEN
         RETURN FALSE;
       ELSE

         found := FALSE;
         done  := FALSE;

         s := 1;

         WHILE ( NOT done ) & ( NOT found ) DO

           (* find the next occurance of the first char of the pattern *)
           WHILE ( s <= len ) & ( CAP(line[s]) # CAP(pattern[0]) ) DO
              s := s + 1;
           END;

           IF s > len THEN
             (* didn't find another first character match *)
             done := TRUE;
           ELSE

             (* try to determine if the pattern fits here *)

             IF len - s + 1 < len_p THEN
               (* the pattern won't fit in the remainder if the source *)
               done := TRUE;
             ELSE

               (* ok, try to make a match *)

               p := 0;
               WHILE ( p < len_p ) & ( CAP(line[s+p]) = CAP(pattern[p]) ) DO
                  p := p + 1;
               END;

               found := p = len_p;

             END;

           END;

           s := s + 1;

         END; (* while *)

         RETURN found;

       END;

    END Contains;

BEGIN EnableBreak;

  n_args := 0;
  REPEAT
    n_args := n_args + 1;
    GetArg( arg[n_args], size[n_args] );
  UNTIL ( n_args = max_args ) OR ( size[n_args] = 0 );

  n_args := n_args - 1;
  IF n_args > 1 THEN

    eof := FALSE;

    RedirectInput( arg[1] );
    IF Done THEN

      ReadLine;
      WHILE NOT eof DO

        (* only try to search though the line if is isn't all blank *)
        IF len > 0 THEN

          (* stop searching if one of the arg strings isn't in this line *)
          i := 2;
          WHILE ( i <= n_args ) & Contains( arg[i], size[i] ) DO
            i := i + 1;
          END;

          IF i > n_args THEN
            WriteString( line ); WriteLn;
          END;

        END;
        ReadLine;
      END;

    ELSE
      WriteString( 'cant open input file ' ); WriteString( arg[1] ); WriteLn;
    END;

  END;
END Search.