
(********************************************************************)
(*                                                                  *)
(*  findchar.sd7  Utility to search for specific chars in files.    *)
(*  Copyright (C) 2010 - 2019  Thomas Mertes                        *)
(*                                                                  *)
(*  This program is free software; you can redistribute it and/or   *)
(*  modify it under the terms of the GNU General Public License as  *)
(*  published by the Free Software Foundation; either version 2 of  *)
(*  the License, or (at your option) any later version.             *)
(*                                                                  *)
(*  This program is distributed in the hope that it will be useful, *)
(*  but WITHOUT ANY WARRANTY; without even the implied warranty of  *)
(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   *)
(*  GNU General Public License for more details.                    *)
(*                                                                  *)
(*  You should have received a copy of the GNU General Public       *)
(*  License along with this program; if not, write to the           *)
(*  Free Software Foundation, Inc., 51 Franklin Street,             *)
(*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
(*                                                                  *)
(********************************************************************)


$ include "seed7_05.s7i";
  include "osfiles.s7i";
  include "getf.s7i";
  include "console.s7i";

var integer: totalCount is 0;


const proc: doFind (in string: fileName, in string: fileContent, in string: searchedChar) is func
  local
    var integer: position is 0;
    var integer: startPos is 0;
    var integer: count is 0;
    var integer: max is 0;
    var integer: maxLine is 1;
  begin
    position := pos(fileContent, searchedChar);
    if position <> 0 then
      write(fileName <& " " <& literal(searchedChar) <& " at " <& position);
      max := pred(position);
      repeat
        incr(count);
        startPos := succ(position);
        position := pos(fileContent, searchedChar, startPos);
        if position <> 0 and position - startPos > max then
          max := position - startPos;
          maxLine := succ(count);
        end if;
      until position = 0;
      if count > 1 then
        write(" found " <& count <& " times");
      end if;
      if searchedChar = "\n" then
        write(", maximum line (" <& maxLine <& ") length: " <& max);
      end if;
      writeln;
    end if;
    totalCount +:= count;
  end func;


const proc: main is func
  local
    var array string: arg_v is 0 times "";
    var integer: arg_number is 2;
    var array string: dir is 0 times "";
    var string: searchedChar is "\r";
    var string: fileName is "";
    var string: dirName is "";
    var string: fileContent is "";
  begin
    OUT := STD_CONSOLE;
    arg_v := argv(PROGRAM);
    if length(arg_v) = 0 then
      writeln("Findchar Version 1.0 - Utility to search for specific characters in files.");
      writeln("Copyright (C) 2010 - 2019 Thomas Mertes");
      writeln("This is free software; see the source for copying conditions.  There is NO");
      writeln("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
      writeln("Findchar is written in the Seed7 programming language");
      writeln("Homepage: http://seed7.sourceforge.net");
      writeln;
      writeln("usage: findchar [ r | t | f | n | s ] { file_name }");
      writeln;
      writeln("The character to search for is specified with a single letter:");
      writeln("r=Return, t=Tab, f=Formfeed, n=Newline, s=Space at end of line");
    else
      if arg_v[1] = "r" then
        searchedChar := "\r";
      elsif arg_v[1] = "t" then
        searchedChar := "\t";
      elsif arg_v[1] = "f" then
        searchedChar := "\f";
      elsif arg_v[1] = "n" then
        searchedChar := "\n";
      elsif arg_v[1] = "s" then
        searchedChar := " \n";
      else
        searchedChar := arg_v[1];
      end if;
      while arg_number <= length(arg_v) do
        fileName := arg_v[arg_number];
        if fileName[length(fileName)] = '/' then
          fileName := fileName[..pred(length(fileName))];
        end if;
        if fileType(fileName) = FILE_DIR then
          dirName := fileName;
          dir := readDir(dirName);
          for fileName range dir do
            fileContent := getf(dirName & "/" & fileName);
            doFind(fileName, fileContent, searchedChar);
          end for;
        else
          fileContent := getf(fileName);
          doFind(fileName, fileContent, searchedChar);
        end if;
        incr(arg_number);
      end while;
    end if;
    if totalCount <> 0 then
      writeln("totally found " <& totalCount <& " times");
    end if;
  end func;
