anchor.diff:      false-> Cnf#cnf{target=to_atom(Str++"@"++element(2,inet:gethostname()))}
     end.
   
  -maybe_print(#cnf{print_depth = Pdepth, print_msec = Pmsec} = Cnf) ->
  -  PF = the_print_fun(Cnf),
  -  Cnf#cnf{print_pid=spawn_link(fun()->print_init(PF,Pdepth,Pmsec) end)}.
  -
  -the_print_fun(Cnf) ->
  -  PrintFun = mk_the_print_fun(Cnf),
  -  fun(print_call)->Cnf#cnf.print_call;
  -     (Str) -> PrintFun(Str)
  -  end.
  -
  -mk_the_print_fun(#cnf{file=[_|_]}) ->
  -  fun(_) -> ok end;
  -mk_the_print_fun(#cnf{print_re="",print_file=F,print_form=Form}) ->
  -  print_fun(get_fd(F),Form);
  -mk_the_print_fun(Cnf = #cnf{print_re=RE}) ->
  -  PF = mk_the_print_fun(Cnf#cnf{print_re=""}),
  -  fun(Str) ->
  -      case re:run(Str,RE) of
  -        nomatch -> ok;
  -        _       -> PF(Str)
  +
  +assert_print_fun(Cnf) -> Cnf#cnf{print_fun=def_print_fun(Cnf)}.
  +
  +spawn_printer(Cnf) ->
  +  Cnf#cnf{print_pid=spawn_link(fun()->print_init(Cnf#cnf.print_fun) end)}.
  +
  +def_print_fun(#cnf{print_fun=PF}) when is_function(PF) -> PF;
  +def_print_fun(Cnf) ->
  +  OutFun = mk_out(Cnf),
  +  fun(Msgs) -> outer(OutFun,Msgs) end.
  +
  +mk_out(#cnf{file=[_|_]}) ->
  +  fun(_,_) -> ok end;
  +mk_out(#cnf{print_re=RE,print_file=File,print_depth=D,print_msec=MS}) ->
  +  fun(F,A) ->
  +      Str=flat(F,[fix_ts(MS,hd(A))|tl(A)]++[D]),
  +      case RE =:= "" andalso re:run(Str,RE) =:= nomatch of
  +        true  -> ok;
  +        false -> io:fwrite(get_fd(File),"~s~n",Str)
         end
     end.
   
  
positive.code:     _ -> exit({cannot_open,FN})
    end.
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%% pack the cnf record into a proplist for prf consumption
  %%% Proplist = list({Tag,Val})
  %%% Tag = time | flags | rtps | procs | where
  %%% Where = {term_buffer,{Pid,Count,MaxQueue,MaxSize}} |
  %%%         {term_stream,{Pid,Count,MaxQueue,MaxSize}} |
  %%%         {file,File,Size,Count} |
  %%%         {ip,Port,Queue}
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  pack(Cnf) ->
    {Flags,RTPs} = foldl(fun chk_trc/2,{[],[]},slist(Cnf#cnf.trc)),
    dict:from_list([{time,chk_time(Cnf#cnf.time)},
                    {flags,[call,timestamp|maybe_arity(Cnf,Flags)]},
                    {rtps,RTPs},
                    {procs,chk_proc(Cnf#cnf.proc)},
                    {where,where(Cnf)}]).
  
  where(Cnf) ->
    case Cnf#cnf.file of
      "" -> conf_term(Cnf);
      _  -> conf_file(Cnf)
    end.
  
  conf_file(Cnf) ->
    {file,Cnf#cnf.file,Cnf#cnf.file_size,Cnf#cnf.file_count}.
  
  conf_term(Cnf) ->
    {chk_buffered(Cnf#cnf.buffered),
     {Cnf#cnf.print_pid,
      chk_msgs(Cnf#cnf.msgs),
      Cnf#cnf.max_queue,
      Cnf#cnf.max_msg_size}}.
  
  maybe_arity(#cnf{arity=true},Flags) -> [arity|Flags];
  maybe_arity(_,Flags)                -> Flags.
  
  chk_time(Time) when is_integer(Time) -> Time;
  chk_time(X) -> exit({bad_time,X}).
  
  chk_buffered(yes) -> term_buffer;
  chk_buffered(no) -> term_stream.
  
  chk_proc(Pid) when is_pid(Pid) -> Pid;
  chk_proc(Atom) when is_atom(Atom)-> Atom;
  chk_proc({pid,I1,I2}) when is_integer(I1), is_integer(I2) -> {pid,I1,I2};
  chk_proc(X) -> exit({bad_proc,X}).
  
  chk_msgs(Msgs) when is_integer(Msgs) -> Msgs;
  chk_msgs(X) -> exit({bad_msgs,X}).
  
  -define(is_string(Str), (Str=="" orelse (9=<hd(Str) andalso hd(Str)=<255))).
  
  chk_trc('send',{Flags,RTPs})                   -> {['send'|Flags],RTPs};
  chk_trc('receive',{Flags,RTPs})                -> {['receive'|Flags],RTPs};
  chk_trc('arity',{Flags,RTPs})                  -> {['arity'|Flags],RTPs};
  chk_trc(RTP,{Flags,RTPs}) when ?is_string(RTP) -> {Flags,[chk_rtp(RTP)|RTPs]};
  chk_trc(RTP,{Flags,RTPs}) when is_tuple(RTP)   -> {Flags,[chk_rtp(RTP)|RTPs]};
  chk_trc(X,_)                                   -> exit({bad_trc,X}).
  
  -define(is_aal(M,F,MS), is_atom(M),is_atom(F),is_list(MS)).
  
  chk_rtp(Str) when ?is_string(Str)      -> redbug_msc:transform(Str);
  chk_rtp({M})                           -> chk_rtp({M,'_',[]});
  chk_rtp({M,F}) when is_atom(F)         -> chk_rtp({M,F,[]});
  chk_rtp({M,L}) when is_list(L)         -> chk_rtp({M,'_',L});
  chk_rtp({'_',_,_})                     -> exit(dont_wildcard_module);
  chk_rtp({M,F,MS}) when ?is_aal(M,F,MS) -> {{M,F,'_'},ms(MS),[local]};
  chk_rtp(X)                             -> exit({bad_rtp,X}).
  
  ms(MS) -> foldl(fun msf/2, [{'_',[],[]}], MS).
  
  msf(stack,[{Head,Cond,Body}]) -> [{Head,Cond,[{message,{process_dump}}|Body]}];
  msf(return,[{Head,Cond,Body}])-> [{Head,Cond,[{return_trace}|Body]}];
  msf(Ari, [{_,Cond,Body}]) when is_integer(Ari)-> [{mk_head(Ari),Cond,Body}];
  msf({Head,Cond},[{_,_,Body}]) when is_tuple(Head)->[{Head,slist(Cond),Body}];
  msf(Head, [{_,Cond,Body}]) when is_tuple(Head)-> [{Head,Cond,Body}];
  msf(X,_) -> exit({bad_match_spec,X}).
  
  mk_head(N) -> erlang:make_tuple(N,'_').
  
  slist(S) when ?is_string(S) -> [S];
  slist(L) when is_list(L) -> usort(L);
  slist(X) -> [X].
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  print_init(PrintFun,Pdepth,Pmsec) ->
    receive
      {trace_consumer,TC} ->
        erlang:monitor(process,TC),
        print_loop(PrintFun,Pdepth,Pmsec)
    end.
  
  print_loop(PrintFun,Pdepth,Pmsec) ->
    receive
      {'DOWN',_,_,_,R} -> io:fwrite("quitting: ~p~n",[R]);
      X -> outer(PrintFun,Pdepth,Pmsec,X),
           print_loop(PrintFun,Pdepth,Pmsec)
    end.
  
  outer(_,_,_,[]) -> ok;
  outer(PrintFun,Pdepth,Pmsec,[Msg|Msgs]) ->
    case Msg of
      {'call',{MFA,Bin},PI,TS} ->
        PrintFun(flat("~n~s <~p> ~P",[ts(TS,Pmsec),PI,MFA,Pdepth])),
        foreach(fun(L)->PrintFun(flat("  ~P",[L,Pdepth])) end, stak(Bin));
      {'retn',{MFA,Val},PI,TS} ->
        PrintFun(flat("~n~s <~p> ~p -> ~P",[ts(TS,Pmsec),PI,MFA,Val,Pdepth]));
      {'send',{MSG,To},PI,TS} ->
        PrintFun(flat("~n~s <~p> <~p> <<< ~P",[ts(TS,Pmsec),PI,To,MSG,Pdepth]));
      {'recv',MSG,PI,TS} ->
        PrintFun(flat("~n~s <~p> <<< ~P",[ts(TS,Pmsec),PI,MSG,Pdepth]));
      _ ->
        PrintFun(flat("~n~P", [Msg,Pdepth]))
    end,
    outer(PrintFun,Pdepth,Pmsec,Msgs).
  
  ts({H,M,S,_Us},false) -> flat("~2.2.0w:~2.2.0w:~2.2.0w",[H,M,S]);
  ts({H,M,S,Us},_) -> flat("~2.2.0w:~2.2.0w:~2.2.0w.~3.3.0w",[H,M,S,Us div 1000]).
  
  flat(Form,List) -> flatten(io_lib:fwrite(Form,List)).
  
  %%% call stack handler
  stak(Bin) ->
  
negative.code:              , cookie       = ''           % target node cookie
               , buffered     = no           % output buffering
               , arity        = false        % arity instead of args
               , print_calls  = true         % print calls
               , print_file   = ""           % file to print to (standard_io)
               , print_msec   = false        % print milliseconds in timestamps?
               , print_depth  = 999999       % Limit for "~P" formatting depth
               , print_re     = ""           % regexp that must match to print
               , print_fun    = ''           % custom print handler
               , max_queue    = 5000         % max # of msgs before suicide
               , max_msg_size = 50000        % max message size before suicide
               , file         = ""           % file to write trace msgs to
  