multiuser report browser enhancements [rb.erl]

Vance Shipley <>
Sat Apr 10 00:12:11 CEST 2004


The attached patch to rb.erl allows users from other nodes
to use the report browser and have the output associated
with their commands go to their screen.  It determines the
group leader of the requesting user and passes this along 
to the print functions.

	-Vance

Vance Shipley
Motivity Telecom Inc.
+1 519 240 3684

-------------- next part --------------
*** rb.erl	Fri Apr  9 17:57:51 2004
--- /Users/otpuser/otp_src_R9C-0/lib/sasl/src/rb.erl	Mon Jul  7 07:59:50 2003
***************
*** 132,221 ****
  	
  init(Options) ->
      process_flag(priority, low),
      process_flag(trap_exit, true),
      Log = get_option(Options, start_log, standard_io),
!     Device = open_log_file(Log, group_leader()),
      Dir = get_report_dir(Options),
      Max = get_option(Options, max, all),
      Type = get_option(Options, type, all),
!     Data = scan_files(Dir ++ "/", Max, Type, group_leader()),
      {ok, #state{dir = Dir ++ "/", data = Data, device = Device,
  		max = Max, type = Type}}.
  
  %% (All those 'catch' are probably unnecessary now that we catch the
  %% formatting in read_rep/4.)
! handle_call({rescan, Options}, {Pid, _Ref}, State) ->
!     {group_leader, Leader} = case is_alive() of
!         true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
!         false -> process_info(Pid, group_leader)
!     end,
      Device = 
  	case get_option(Options, start_log, {undefined}) of
  	    {undefined} -> State#state.device;
  	    Log ->
  		close_device(State#state.device),
! 		open_log_file(Log, Leader)
  	end,
      Max = get_option(Options, max, State#state.max),
      Type = get_option(Options, type, State#state.type),
!     Data = scan_files(State#state.dir, Max, Type, Leader),
      NewState = State#state{data = Data, max = Max, type = Type,
  			   device = Device},
      {reply, ok, NewState};
  handle_call(stop, _From, State) ->
      {stop, normal, stopped, State};
  handle_call(_, _From, #state{data = undefined}) ->
      {reply, {error, no_data}, #state{}};
! handle_call({list, Type}, {Pid, _Ref}, State) ->
!     {group_leader, Leader} = case is_alive() of
!         true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
!         false -> process_info(Pid, group_leader)
!     end,
!     print_list(State#state.data, Type, Leader),
      {reply, ok, State};
! handle_call({start_log, FileName}, {Pid, _Ref}, State) ->
!     {group_leader, Leader} = case is_alive() of
!         true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
!         false -> process_info(Pid, group_leader)
!     end,
!     NewDevice = open_log_file(FileName, Leader),
      {reply, ok, State#state{device = NewDevice}};
  handle_call(stop_log, _From, State) ->
      close_device(State#state.device),
      {reply, ok, State#state{device = standard_io}};
! handle_call({show_number, Number}, {Pid, _Ref}, State) ->
      #state{dir = Dir, data = Data, device = Device} = State,
!     {group_leader, Leader} = case is_alive() of
!         true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
!         false -> process_info(Pid, group_leader)
!     end,
!     catch print_report(Dir, Data, Number, Device, Leader),
      {reply, ok, State};
! handle_call({show_type, Type}, {Pid, _Ref}, State) ->
      #state{dir = Dir, data = Data, device = Device} = State,
!     {group_leader, Leader} = case is_alive() of
!         true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
!         false -> process_info(Pid, group_leader)
!     end,
!     catch print_typed_reports(Dir, Data, Type, Device, Leader),
      {reply, ok, State};
! handle_call(show, {Pid, _Ref}, State) ->
      #state{dir = Dir, data = Data, device = Device} = State,
!     {group_leader, Leader} = case is_alive() of
!         true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
!         false -> process_info(Pid, group_leader)
!     end,
!     catch print_all_reports(Dir, Data, Device, Leader),
      {reply, ok, State};
! handle_call({grep, RegExp}, {Pid, _Ref}, State) ->
      #state{dir = Dir, data = Data, device = Device} = State,
!     {group_leader, Leader} = case is_alive() of
!         true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
!         false -> process_info(Pid, group_leader)
!     end,
!     catch print_grep_reports(Dir, Data, RegExp, Device, Leader),
      {reply, ok, State}.
  
  terminate(_Reason, #state{device = Device}) ->
      close_device(Device).
  
--- 132,193 ----
  	
  init(Options) ->
      process_flag(priority, low),
      process_flag(trap_exit, true),
      Log = get_option(Options, start_log, standard_io),
!     Device = open_log_file(Log),
      Dir = get_report_dir(Options),
      Max = get_option(Options, max, all),
      Type = get_option(Options, type, all),
!     Data = scan_files(Dir ++ "/", Max, Type),
      {ok, #state{dir = Dir ++ "/", data = Data, device = Device,
  		max = Max, type = Type}}.
  
  %% (All those 'catch' are probably unnecessary now that we catch the
  %% formatting in read_rep/4.)
! handle_call({rescan, Options}, _From, State) ->
      Device = 
  	case get_option(Options, start_log, {undefined}) of
  	    {undefined} -> State#state.device;
  	    Log ->
  		close_device(State#state.device),
! 		open_log_file(Log)
  	end,
      Max = get_option(Options, max, State#state.max),
      Type = get_option(Options, type, State#state.type),
!     Data = scan_files(State#state.dir, Max, Type),
      NewState = State#state{data = Data, max = Max, type = Type,
  			   device = Device},
      {reply, ok, NewState};
  handle_call(stop, _From, State) ->
      {stop, normal, stopped, State};
  handle_call(_, _From, #state{data = undefined}) ->
      {reply, {error, no_data}, #state{}};
! handle_call({list, Type}, _From, State) ->
!     print_list(State#state.data, Type),
      {reply, ok, State};
! handle_call({start_log, FileName}, _From, State) ->
!     NewDevice = open_log_file(FileName),
      {reply, ok, State#state{device = NewDevice}};
  handle_call(stop_log, _From, State) ->
      close_device(State#state.device),
      {reply, ok, State#state{device = standard_io}};
! handle_call({show_number, Number}, _From, State) ->
      #state{dir = Dir, data = Data, device = Device} = State,
!     catch print_report(Dir, Data, Number, Device),
      {reply, ok, State};
! handle_call({show_type, Type}, _From, State) ->
      #state{dir = Dir, data = Data, device = Device} = State,
!     catch print_typed_reports(Dir, Data, Type, Device),
      {reply, ok, State};
! handle_call(show, _From, State) ->
      #state{dir = Dir, data = Data, device = Device} = State,
!     catch print_all_reports(Dir, Data, Device),
      {reply, ok, State};
! handle_call({grep, RegExp}, _From, State) ->
      #state{dir = Dir, data = Data, device = Device} = State,
!     catch print_grep_reports(Dir, Data, RegExp, Device),
      {reply, ok, State}.
  
  terminate(_Reason, #state{device = Device}) ->
      close_device(Device).
  
***************
*** 225,247 ****
      {noreply, State}.
  code_change(OldVsn, State, Extra) ->
      {ok, State}.
  
  %%-----------------------------------------------------------------
! %% Func: open_log_file/2
  %% Args: FileName | standard_io
- %%       Leader ::= pid(), the group_leader to send io to
  %% Returns: A Device for later use in call to io:format
  %%-----------------------------------------------------------------
! open_log_file(standard_io, _Leader) -> standard_io;
! open_log_file(FileName, Leader) ->
      case file:open(FileName, write) of
  	{ok, Fd} -> Fd;
  	Error -> 
! 	    io:format(Leader, "rb: Cannot open file '~s' (~w).~n",
  		      [FileName, Error]),
! 	    io:format(Leader, "rb: Using standard_io~n", []),
  	    standard_io
      end.
  
  close_device(Fd) when pid(Fd) ->
      catch file:close(Fd);
--- 197,218 ----
      {noreply, State}.
  code_change(OldVsn, State, Extra) ->
      {ok, State}.
  
  %%-----------------------------------------------------------------
! %% Func: open_log_file/1
  %% Args: FileName | standard_io
  %% Returns: A Device for later use in call to io:format
  %%-----------------------------------------------------------------
! open_log_file(standard_io) -> standard_io;
! open_log_file(FileName) ->
      case file:open(FileName, write) of
  	{ok, Fd} -> Fd;
  	Error -> 
! 	    io:format("rb: Cannot open file '~s' (~w).~n",
  		      [FileName, Error]),
! 	    io:format("rb: Using standard_io~n"),
  	    standard_io
      end.
  
  close_device(Fd) when pid(Fd) ->
      catch file:close(Fd);
***************
*** 263,290 ****
  		    exit("cannot locate report directory")
  	    end
      end.
  
  %%-----------------------------------------------------------------
! %% Func: scan_files(RptDir, Max, Type, Leader)
  %% Args: RptDir ::= string().
  %%       Max ::= integer() | all, describing how many reports
  %5               to read.
  %%       Type ::= atom(), describing which reports to read.
- %%       Leader ::= pid(), the group_leader to send io to
  %% Purpose: Scan all report files one time, and build a list of
  %%          small elements 
  %% Returns: Data, where Data is a list of
  %%          {Number, Type, ShortDescr, Date, Fname, FilePosition}.
  %%-----------------------------------------------------------------
! scan_files(RptDir, Max, Type, Leader) ->
      case file:open(RptDir ++ "/index", [raw, read]) of
  	{ok, Fd} ->
  	    case catch file:read(Fd, 1) of
  		{ok, [LastWritten]} -> 
  		    Files = make_file_list(RptDir, LastWritten),
! 		    scan_files(RptDir, Files, Max, Type, Leader);		
  		_ -> exit("cannot read the index file")
  	    end;
  	_ -> exit("cannot read the index file")
      end.
  
--- 234,260 ----
  		    exit("cannot locate report directory")
  	    end
      end.
  
  %%-----------------------------------------------------------------
! %% Func: scan_files(RptDir, Max, Type)
  %% Args: RptDir ::= string().
  %%       Max ::= integer() | all, describing how many reports
  %5               to read.
  %%       Type ::= atom(), describing which reports to read.
  %% Purpose: Scan all report files one time, and build a list of
  %%          small elements 
  %% Returns: Data, where Data is a list of
  %%          {Number, Type, ShortDescr, Date, Fname, FilePosition}.
  %%-----------------------------------------------------------------
! scan_files(RptDir, Max, Type) ->
      case file:open(RptDir ++ "/index", [raw, read]) of
  	{ok, Fd} ->
  	    case catch file:read(Fd, 1) of
  		{ok, [LastWritten]} -> 
  		    Files = make_file_list(RptDir, LastWritten),
! 		    scan_files(RptDir, Files, Max, Type);		
  		_ -> exit("cannot read the index file")
  	    end;
  	_ -> exit("cannot read the index file")
      end.
  
***************
*** 318,387 ****
  %% Func: scan_files(Dir, Files, Max, Type)
  %% Args: Files is a list of FileName.
  %% Purpose: Scan the report files in the index variable.
  %% Returns: {Number, Type, ShortDescr, Date, FileName, FilePosition}
  %%-----------------------------------------------------------------
! scan_files(Dir, Files, Max, Type, Leader) ->
!     scan_files(Dir, 1, Files, [], Max, Type, Leader).
! scan_files(Dir, _, [], Res, Max, Type, Leader) -> Res;
! scan_files(Dir, _, Files, Res, Max, Type, Leader) when Max =< 0 -> Res;
! scan_files(Dir, No, [H|T], Res, Max, Type, Leader) ->
!     Data = get_report_data_from_file(Dir, No, H, Max, Type, Leader),
      Len = length(Data),
      NewMax = dec_max(Max, Len),
      NewNo = No + Len,
      NewData = Data ++ Res,
!     scan_files(Dir, NewNo, T, NewData, NewMax, Type, Leader).
  
  dec_max(all, _) -> all;
  dec_max(X,Y) -> X-Y.
  
! get_report_data_from_file(Dir, No, FileNr, Max, Type, Leader) ->	
      Fname = integer_to_list(FileNr),
      FileName = lists:concat([Dir, Fname]),
      case file:open(FileName, read) of
! 	{ok, Fd} when pid(Fd) -> read_reports(No, Fd, Fname, Max, Type, Leader);
  	_ -> [{No, unknown, "Can't open file " ++ Fname, "???", Fname, 0}]
      end.
  
  %%-----------------------------------------------------------------
! %% Func: read_reports(No, Fd, Fname, Max, Type, Leader)
  %% Purpose: Read reports from one report file.
  %% Returns: A list of {No, Type, ShortDescr, Date, FileName, FilePosition}
  %% Note: We have to read all reports, and then check the max-
  %%       variable, because the reports are reversed on the file, and
  %%       we may need the last ones.
  %%-----------------------------------------------------------------
! read_reports(No, Fd, Fname, Max, Type, Leader) ->
!     io:format(Leader, "rb: reading report...", []),
      case catch read_reports(Fd, [], Type) of
  	{ok, Res} -> 
  	    file:close(Fd),
! 	    io:format(Leader, "done.~n", []),
  	    NewRes = 
  		if
  		    length(Res) > Max ->
  			lists:sublist(Res, 1, Max);
  		    true ->
  			Res
  		end,
  	    add_report_data(NewRes, No, Fname);
  	{error, [Problem | Res]} ->
  	    file:close(Fd),
! 	    io:format(Leader, "Error: ~p~n",[Problem]),
! 	    io:format(Leader, "Salvaged ~p entries from corrupt report file ~s...~n",
  		      [length(Res),Fname]),
  	    NewRes = 
  		if
  		    length([Problem|Res]) > Max ->
  			lists:sublist([Problem|Res], 1, Max);
  		    true ->
  			[Problem|Res]
  		end,
  	    add_report_data(NewRes, No, Fname);
  	Else ->
! 	    io:format(Leader, "err ~p~n", [Else]),
  	    [{No, unknown, "Can't read reports from file " ++ Fname,
  		  "???", Fname, 0}]
      end.
  
  %%-----------------------------------------------------------------
--- 288,357 ----
  %% Func: scan_files(Dir, Files, Max, Type)
  %% Args: Files is a list of FileName.
  %% Purpose: Scan the report files in the index variable.
  %% Returns: {Number, Type, ShortDescr, Date, FileName, FilePosition}
  %%-----------------------------------------------------------------
! scan_files(Dir, Files, Max, Type) ->
!     scan_files(Dir, 1, Files, [], Max, Type).
! scan_files(Dir, _, [], Res, Max, Type) -> Res;
! scan_files(Dir, _, Files, Res, Max, Type) when Max =< 0 -> Res;
! scan_files(Dir, No, [H|T], Res, Max, Type) ->
!     Data = get_report_data_from_file(Dir, No, H, Max, Type),
      Len = length(Data),
      NewMax = dec_max(Max, Len),
      NewNo = No + Len,
      NewData = Data ++ Res,
!     scan_files(Dir, NewNo, T, NewData, NewMax, Type).
  
  dec_max(all, _) -> all;
  dec_max(X,Y) -> X-Y.
  
! get_report_data_from_file(Dir, No, FileNr, Max, Type) ->	
      Fname = integer_to_list(FileNr),
      FileName = lists:concat([Dir, Fname]),
      case file:open(FileName, read) of
! 	{ok, Fd} when pid(Fd) -> read_reports(No, Fd, Fname, Max, Type);
  	_ -> [{No, unknown, "Can't open file " ++ Fname, "???", Fname, 0}]
      end.
  
  %%-----------------------------------------------------------------
! %% Func: read_reports(No, Fd, Fname, Max, Type)
  %% Purpose: Read reports from one report file.
  %% Returns: A list of {No, Type, ShortDescr, Date, FileName, FilePosition}
  %% Note: We have to read all reports, and then check the max-
  %%       variable, because the reports are reversed on the file, and
  %%       we may need the last ones.
  %%-----------------------------------------------------------------
! read_reports(No, Fd, Fname, Max, Type) ->
!     io:format("rb: reading report..."),
      case catch read_reports(Fd, [], Type) of
  	{ok, Res} -> 
  	    file:close(Fd),
! 	    io:format("done.~n"),
  	    NewRes = 
  		if
  		    length(Res) > Max ->
  			lists:sublist(Res, 1, Max);
  		    true ->
  			Res
  		end,
  	    add_report_data(NewRes, No, Fname);
  	{error, [Problem | Res]} ->
  	    file:close(Fd),
! 	    io:format("Error: ~p~n",[Problem]),
! 	    io:format("Salvaged ~p entries from corrupt report file ~s...~n",
  		      [length(Res),Fname]),
  	    NewRes = 
  		if
  		    length([Problem|Res]) > Max ->
  			lists:sublist([Problem|Res], 1, Max);
  		    true ->
  			[Problem|Res]
  		end,
  	    add_report_data(NewRes, No, Fname);
  	Else ->
! 	    io:format("err ~p~n", [Else]),
  	    [{No, unknown, "Can't read reports from file " ++ Fname,
  		  "???", Fname, 0}]
      end.
  
  %%-----------------------------------------------------------------
***************
*** 509,530 ****
      end.
  
  
  
  
! print_list(Data, Type, Leader) ->
      Header = {"No", "Type", "Process", "Date     Time"},
      Width = find_width([Header | Data], 0)+1,
      DateWidth = find_date_width([Header | Data], 0) +1,
      Format = lists:concat(["~4s~20s ~", Width, "s~20s~n"]),
!     io:format(Leader, Format, tuple_to_list(Header)),
!     io:format(Leader, Format, ["==", "====", "=======", "====     ===="]),
!     print_list(Data, Type, Width, DateWidth, Leader).
! print_list([], _, _, _, _) -> true;
! print_list([H|T], Type, Width, DateWidth, Leader) ->
!     print_one_report(H, Type, Width, DateWidth, Leader),
!     print_list(T, Type, Width, DateWidth, Leader).
  
  find_width([], Width) -> Width;
  find_width([H|T], Width) ->
      Try = length(element(3, H)),
      if
--- 479,500 ----
      end.
  
  
  
  
! print_list(Data, Type) ->
      Header = {"No", "Type", "Process", "Date     Time"},
      Width = find_width([Header | Data], 0)+1,
      DateWidth = find_date_width([Header | Data], 0) +1,
      Format = lists:concat(["~4s~20s ~", Width, "s~20s~n"]),
!     io:format(Format, tuple_to_list(Header)),
!     io:format(Format, ["==", "====", "=======", "====     ===="]),
!     print_list(Data, Type, Width, DateWidth).
! print_list([], _, _, _) -> true;
! print_list([H|T], Type, Width, DateWidth) ->
!     print_one_report(H, Type, Width, DateWidth),
!     print_list(T, Type, Width, DateWidth).
  
  find_width([], Width) -> Width;
  find_width([H|T], Width) ->
      Try = length(element(3, H)),
      if
***************
*** 539,643 ****
  	true -> find_date_width(T, Width)
      end.
  
  print_one_report({No, RealType, ShortDescr, Date, Fname, FilePosition},
  		 WantedType,
! 		 Width, DateWidth, Leader) ->
      if
  	WantedType == all ->
  	    print_short_descr(No, RealType, ShortDescr, Date, Width, 
! 			      DateWidth, Leader);
  	WantedType == RealType ->
  	    print_short_descr(No, RealType, ShortDescr, Date, Width, 
! 			      DateWidth, Leader);
  	true -> ok
      end.
  
! print_short_descr(No, Type, ShortDescr, Date, Width, DateWidth, Leader) ->
      Format = lists:concat(["~4w~20w ~", Width, "s~", DateWidth,"s~n"]),
!     io:format(Leader, Format, [No,
  		       Type, 
  		       io_lib:format("~s", [ShortDescr]),
  		       Date]).
  
! print_typed_reports(Dir, [], _Type, _Device, _Leader) ->
      ok;
! print_typed_reports(Dir, Data, Type, Device, Leader) ->
      case element(2, hd(Data)) of
! 	Type -> print_report(Dir, Data, element(1, hd(Data)), Device, Leader);
  	_ -> ok
      end,
!     print_typed_reports(Dir, tl(Data), Type, Device, Leader).    
  
! print_all_reports(Dir, [], _Device, _Leader) ->
      ok;
! print_all_reports(Dir, Data, Device, Leader) ->
!     print_report(Dir, Data, element(1, hd(Data)), Device, Leader),
!     print_all_reports(Dir, tl(Data), Device, Leader).    
  
! print_report(Dir, Data, Number, Device, Leader) ->
      {Fname, FilePosition, Type} = find_report(Data, Number),
      FileName = lists:concat([Dir, Fname]),
      case file:open(FileName, read) of
! 	{ok, Fd} -> read_rep(Fd, FilePosition, Type, Device, Leader);
! 	_ -> io:format(Leader, "rb: can't open file ~p~n", [Fname])
      end.
  
  find_report([{No, Type, ShortDescr, Date, Fname, FilePosition}|T], No) ->
      {Fname, FilePosition, Type};
  find_report([H|T], No) -> find_report(T, No);
  find_report([], No) ->
      io:format("There is no report with number ~p.~n", [No]).
      
! print_grep_reports(_Dir, [], _RegExp, _Device, _Leader) ->
      ok;
! print_grep_reports(Dir, Data, RegExp, Device, Leader) ->
!     print_grep_report(Dir, Data, element(1, hd(Data)), Device, Leader, RegExp),
!     print_grep_reports(Dir, tl(Data), RegExp, Device, Leader).    
  
! print_grep_report(Dir, Data, Number, Device, Leader, RegExp) ->
      {Fname, FilePosition, Type} = find_report(Data, Number),
      FileName = lists:concat([Dir, Fname]),
      case file:open(FileName, read) of
  	{ok, Fd} when pid(Fd) -> 
! 	    check_rep(Fd, FilePosition, Type, Device, Leader, RegExp, Number);
  	_ -> 
! 	    io:format(Leader, "rb: can't open file ~p~n", [Fname])
      end.
  
! check_rep(Fd, FilePosition, Type, Device, Leader, RegExp, Number) ->
      case read_rep_msg(Fd, FilePosition, Type) of
  	{Date, Msg} ->
  	    MsgStr = lists:flatten(io_lib:format("~p",[Msg])),
  	    case regexp:match(MsgStr, RegExp) of
! 	        {match, _, _} ->
! 	            io:format(Leader, "Found match in report number ~w~n", [Number]),
! 	            case Device of
! 	                standard_io -> rb_format_supp:print(Date, Msg, Leader);
! 	                _ -> rb_format_supp:print(Date, Msg, Device)
! 	            end;
! 	        _ -> false
  	    end;
  	_ ->
! 	    io:format(Leader, "rb: Cannot read from file~n", [])
      end.
  
! read_rep(Fd, FilePosition, Type, Device, Leader) ->
      case read_rep_msg(Fd, FilePosition, Type) of
  	{Date, Msg} ->
! 	    Log = case Device of
! 	        standard_io -> Leader;
! 	        _ ->Device 
! 	    end,
! 	    case catch rb_format_supp:print(Date, Msg, Log) of
  		{'EXIT', _} ->
  		    io:format(Device, "ERROR: ~p ~p~n", [Date, Msg]);
  		_ ->
  		    ok
  	    end;
  	_ -> 
! 	    io:format(Leader, "rb: Cannot read from file~n", [])
      end.
      
  read_rep_msg(Fd, FilePosition, Type) ->
      file:position(Fd, {bof, FilePosition}),
      Res = 
--- 509,606 ----
  	true -> find_date_width(T, Width)
      end.
  
  print_one_report({No, RealType, ShortDescr, Date, Fname, FilePosition},
  		 WantedType,
! 		 Width, DateWidth) ->
      if
  	WantedType == all ->
  	    print_short_descr(No, RealType, ShortDescr, Date, Width, 
! 			      DateWidth);
  	WantedType == RealType ->
  	    print_short_descr(No, RealType, ShortDescr, Date, Width, 
! 			      DateWidth);
  	true -> ok
      end.
  
! print_short_descr(No, Type, ShortDescr, Date, Width, DateWidth) ->
      Format = lists:concat(["~4w~20w ~", Width, "s~", DateWidth,"s~n"]),
!     io:format(Format, [No,
  		       Type, 
  		       io_lib:format("~s", [ShortDescr]),
  		       Date]).
  
! print_typed_reports(Dir, [], Type, Device) ->
      ok;
! print_typed_reports(Dir, Data, Type, Device) ->
      case element(2, hd(Data)) of
! 	Type -> print_report(Dir, Data, element(1, hd(Data)), Device);
  	_ -> ok
      end,
!     print_typed_reports(Dir, tl(Data), Type, Device).    
  
! print_all_reports(Dir, [], Device) ->
      ok;
! print_all_reports(Dir, Data, Device) ->
!     print_report(Dir, Data, element(1, hd(Data)), Device),
!     print_all_reports(Dir, tl(Data), Device).    
  
! print_report(Dir, Data, Number, Device) ->
      {Fname, FilePosition, Type} = find_report(Data, Number),
      FileName = lists:concat([Dir, Fname]),
      case file:open(FileName, read) of
! 	{ok, Fd} -> read_rep(Fd, FilePosition, Type, Device);
! 	_ -> io:format("rb: can't open file ~p~n", [Fname])
      end.
  
  find_report([{No, Type, ShortDescr, Date, Fname, FilePosition}|T], No) ->
      {Fname, FilePosition, Type};
  find_report([H|T], No) -> find_report(T, No);
  find_report([], No) ->
      io:format("There is no report with number ~p.~n", [No]).
      
! print_grep_reports(Dir, [], RegExp, Device) ->
      ok;
! print_grep_reports(Dir, Data, RegExp, Device) ->
!     print_grep_report(Dir, Data, element(1, hd(Data)), Device, RegExp),
!     print_grep_reports(Dir, tl(Data), RegExp, Device).    
  
! print_grep_report(Dir, Data, Number, Device, RegExp) ->
      {Fname, FilePosition, Type} = find_report(Data, Number),
      FileName = lists:concat([Dir, Fname]),
      case file:open(FileName, read) of
  	{ok, Fd} when pid(Fd) -> 
! 	    check_rep(Fd, FilePosition, Type, Device, RegExp, Number);
  	_ -> 
! 	    io:format("rb: can't open file ~p~n", [Fname])
      end.
  
! check_rep(Fd, FilePosition, Type, Device, RegExp, Number) ->
      case read_rep_msg(Fd, FilePosition, Type) of
  	{Date, Msg} ->
  	    MsgStr = lists:flatten(io_lib:format("~p",[Msg])),
  	    case regexp:match(MsgStr, RegExp) of
! 		{match, _, _} ->
! 		    io:format("Found match in report number ~w~n", [Number]),
! 		    rb_format_supp:print(Date, Msg, Device);
! 		_ -> false
  	    end;
  	_ ->
! 	    io:format("rb: Cannot read from file~n")
      end.
  
! read_rep(Fd, FilePosition, Type, Device) ->
      case read_rep_msg(Fd, FilePosition, Type) of
  	{Date, Msg} ->
! 	    case catch rb_format_supp:print(Date, Msg, Device) of
  		{'EXIT', _} ->
  		    io:format(Device, "ERROR: ~p ~p~n", [Date, Msg]);
  		_ ->
  		    ok
  	    end;
  	_ -> 
! 	    io:format("rb: Cannot read from file~n")
      end.
      
  read_rep_msg(Fd, FilePosition, Type) ->
      file:position(Fd, {bof, FilePosition}),
      Res = 


More information about the erlang-patches mailing list