From luke@REDACTED Thu Apr 1 11:56:55 2004 From: luke@REDACTED (Luke Gorrie) Date: Thu, 01 Apr 2004 11:56:55 +0200 Subject: dbg_iload:guard_test/1 patch Message-ID: Ahoy, The patch below adds support for two types of guards in the debugger's Erlang interpreter: Var not It just translates them into: Var == true /= true These seem to be new features added to Erlang but not this interpreter. If you use these guards in your programs and you have seen Distel blowing up when you interpret your modules, I recommend applying this in lib/debugger/src/ :-) P.S., is there any technical reason not to rewrite the Erlang interpreters in the debugger and/or shell to interpret Core Erlang instead? -------------- next part -------------- A non-text attachment was scrubbed... Name: dbg_iload.patch Type: text/x-patch Size: 734 bytes Desc: guard_test/1 fix URL: From dgud@REDACTED Thu Apr 1 12:11:16 2004 From: dgud@REDACTED (Dan Gudmundsson) Date: Thu, 1 Apr 2004 12:11:16 +0200 Subject: dbg_iload:guard_test/1 patch In-Reply-To: References: Message-ID: <16491.60100.689441.977955@rian.du.uab.ericsson.se> I have already fixed that, along with a long list of other bugs. It will be available in next erlang release. Cheers /Dan Luke Gorrie writes: > Ahoy, > > The patch below adds support for two types of guards in the > debugger's Erlang interpreter: > > Var > not > > It just translates them into: > > Var == true > /= true > > These seem to be new features added to Erlang but not this > interpreter. > > If you use these guards in your programs and you have seen Distel > blowing up when you interpret your modules, I recommend applying this > in lib/debugger/src/ :-) > > P.S., is there any technical reason not to rewrite the Erlang > interpreters in the debugger and/or shell to interpret Core Erlang > instead? > > --- dbg_iload.erl.~1.1.1.5.~ 2003-09-02 15:34:28.000000000 +0200 > +++ dbg_iload.erl 2004-04-01 11:29:01.000000000 +0200 > @@ -243,6 +243,8 @@ > error -> > {safe_bif,Line,erlang,F,As} > end; > +guard_test({op,Line,'not',L0}) -> > + guard_test({op,Line,'/=',L0,{atom,Line,true}}); > guard_test({op,Line,Op,L0}) -> > true = erl_internal:arith_op(Op, 1), %Assertion. > L1 = gexpr(L0), > @@ -258,7 +260,8 @@ > guard_test({char,_,_}=C) -> C; > guard_test({float,_,_}=F) -> F; > guard_test({atom,_,_}=A) -> A; > -guard_test({nil,_}=N) -> N. > +guard_test({nil,_}=N) -> N; > +guard_test({var,Line,_}=V) -> guard_test({op,Line,'==',V,{atom,Line,true}}). > > map_guard_bif(integer, 1) -> {ok,is_integer}; > map_guard_bif(float, 1) -> {ok,is_float}; -- Dan Gudmundsson Project: Mnesia, Erlang/OTP Ericsson Utvecklings AB Phone: +46 8 727 5762 UAB/F/P Mobile: +46 70 519 9469 S-125 25 Stockholm Visit addr: Armborstv 1 From vances@REDACTED Fri Apr 2 21:42:54 2004 From: vances@REDACTED (Vance Shipley) Date: Fri, 2 Apr 2004 14:42:54 -0500 Subject: ets:from_dets/2 doesn't act as documented In-Reply-To: <20040213234835.GA9716@frogman.motivity.ca> References: <20040213234835.GA9716@frogman.motivity.ca> Message-ID: <20040402194254.GH75018@frogman.motivity.ca> The ets:to_dets documentation is correct: "The DETS table is emptied before the objects are inserted." The ets:from_dets documentation is wrong: "The ETS table is emptied before the objects are inserted." The dets:from_ets documentation isn't clear: "Replaces the objects of the table Name with the objects of the Ets table EtsTab." The dets:to_ets documentation is correct: "The existing objects of the Ets table are kept unless overwritten." From luke@REDACTED Tue Apr 6 14:23:39 2004 From: luke@REDACTED (Luke Gorrie) Date: Tue, 06 Apr 2004 14:23:39 +0200 Subject: dbg_iload:guard_test/1 patch In-Reply-To: <16491.60100.689441.977955@rian.du.uab.ericsson.se> (Dan Gudmundsson's message of "Thu, 1 Apr 2004 12:11:16 +0200") References: <16491.60100.689441.977955@rian.du.uab.ericsson.se> Message-ID: Dan Gudmundsson writes: > I have already fixed that, along with a long list of other bugs. > It will be available in next erlang release. We're hitting another debugger crash. This time it's a 'badarg' from the erts_debug:make_fun when called from dbg_ieval:expr. I don't have the exact backtrace handy, but conspicously the 'Uniq' variable was bound to 'undefined'. Does that sound like something you've fixed? Are there still OTP snapshots stashed in secret hideouts on the web? I could use one to diff against. -Luke From dgud@REDACTED Tue Apr 6 14:26:48 2004 From: dgud@REDACTED (Dan Gudmundsson) Date: Tue, 6 Apr 2004 14:26:48 +0200 Subject: dbg_iload:guard_test/1 patch In-Reply-To: References: <16491.60100.689441.977955@rian.du.uab.ericsson.se> Message-ID: <16498.41480.813189.195618@rian.du.uab.ericsson.se> Luke Gorrie writes: > Dan Gudmundsson writes: > > > I have already fixed that, along with a long list of other bugs. > > It will be available in next erlang release. > > We're hitting another debugger crash. This time it's a 'badarg' from > the erts_debug:make_fun when called from dbg_ieval:expr. I don't have > the exact backtrace handy, but conspicously the 'Uniq' variable was > bound to 'undefined'. > > Does that sound like something you've fixed? I don't know, I have rewritten how funs are handled, Probably because the erts_debug:make_fun are never called now. > Are there still OTP snapshots stashed in secret hideouts on the web? > I could use one to diff against. I don't know.. > -Luke /Dan From vances@REDACTED Sat Apr 10 00:12:11 2004 From: vances@REDACTED (Vance Shipley) Date: Fri, 9 Apr 2004 18:12:11 -0400 Subject: multiuser report browser enhancements [rb.erl] Message-ID: <20040409221211.GA5214@frogman.motivity.ca> 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 vances@REDACTED -------------- 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 = From svg@REDACTED Tue Apr 13 12:06:51 2004 From: svg@REDACTED (Vladimir Sekissov) Date: Tue, 13 Apr 2004 16:06:51 +0600 (YEKST) Subject: Erl_call bug in R9C-0 Message-ID: <20040413.160651.59676035.svg@surnet.ru> Good day, There is small bug in lib/erl_interface/src/prog/erl_call.c from R9C-0. Here is a patch. Best Regards, Vladimir Sekissov diff -Naur otp_src_R9C-0.orig/lib/erl_interface/src/prog/erl_call.c otp_src_R9C-0/lib/erl_interface/src/prog/erl_call.c --- otp_src_R9C-0.orig/lib/erl_interface/src/prog/erl_call.c 2003-08-01 15:07:02.000000000 +0600 +++ otp_src_R9C-0/lib/erl_interface/src/prog/erl_call.c 2004-04-13 14:04:26.000000000 +0600 @@ -512,14 +512,14 @@ ei_x_buff reply; ei_encode_list_header(NULL, &i, 1); - ei_encode_binary(NULL, &i, module, modsize); + ei_encode_string_len(NULL, &i, evalbuf, len); ei_encode_empty_list(NULL, &i); p = (char *)malloc(i); i = 0; /* Reset */ ei_encode_list_header(p, &i, 1); - ei_encode_binary(p, &i, module, modsize); + ei_encode_string_len(p, &i, evalbuf, len); ei_encode_empty_list(p, &i); ei_x_new_with_version(&reply); From kent@REDACTED Thu Apr 15 05:42:11 2004 From: kent@REDACTED (Kent Boortz) Date: 15 Apr 2004 05:42:11 +0200 Subject: Erl_call bug in R9C-0 In-Reply-To: <20040413.160651.59676035.svg@surnet.ru> References: <20040413.160651.59676035.svg@surnet.ru> Message-ID: Sorry about this, it is a typical "copy and paste" bug :-( We are expanding the test cases for 'erl_interface' but haven't added any for erl_call yet. Seem to be enough just to change the arguments, no need to use ei_encode_string_len() that I can see, do you know a reason? % echo 'X=1,Y=2,{X,Y}.' | erl_call -sname foo -e {ok, {1, 2}} Thank you for reporting this, kent Vladimir Sekissov writes: > There is small bug in lib/erl_interface/src/prog/erl_call.c from > R9C-0. > > Here is a patch. > > Best Regards, > Vladimir Sekissov > > diff -Naur otp_src_R9C-0.orig/lib/erl_interface/src/prog/erl_call.c otp_src_R9C-0/lib/erl_interface/src/prog/erl_call.c > --- otp_src_R9C-0.orig/lib/erl_interface/src/prog/erl_call.c 2003-08-01 15:07:02.000000000 +0600 > +++ otp_src_R9C-0/lib/erl_interface/src/prog/erl_call.c 2004-04-13 14:04:26.000000000 +0600 > @@ -512,14 +512,14 @@ > ei_x_buff reply; > > ei_encode_list_header(NULL, &i, 1); > - ei_encode_binary(NULL, &i, module, modsize); > + ei_encode_string_len(NULL, &i, evalbuf, len); > ei_encode_empty_list(NULL, &i); > > p = (char *)malloc(i); > i = 0; /* Reset */ > > ei_encode_list_header(p, &i, 1); > - ei_encode_binary(p, &i, module, modsize); > + ei_encode_string_len(p, &i, evalbuf, len); > ei_encode_empty_list(p, &i); > > ei_x_new_with_version(&reply);