anchor.diff:  compiler(".py") ->     {asn1ct,          compile_py};
   compiler(_) ->         no.
   
  -%% Entry from command line.
  -
   -type cmd_line_arg() :: atom() | string().
   
  +%% Run a compilation based on the command line arguments and then halt.
  +%% Intended for one-off compilation by erlc.
   -spec compile_cmdline() -> no_return().
  -
   compile_cmdline() ->
  +    cmdline_init(),
       List = init:get_plain_arguments(),
  -    case compile(List) of
  -	ok -> my_halt(0);
  -	error -> my_halt(1);
  -	_ -> my_halt(2)
  -    end.
  -
  --spec my_halt(_) -> no_return().
  -my_halt(Reason) ->
  -    erlang:halt(Reason).
  -
  -%% Run the the compiler in a separate process, trapping EXITs.
  -
  -compile(List) ->
  -    process_flag(trap_exit, true),
  -    Pid = spawn_link(compiler_runner(List)),
  +    compile_cmdline1(List).
  +
  +%% Run a compilation. Meant to be used by the compilation server.
  +-spec compile(list(), file:filename()) -> 'ok' | {'error', binary()}.
  +compile(Args, Cwd) ->
  +    try compile1(Args, #options{outdir=Cwd,cwd=Cwd}) of
  +        ok ->
  +            ok
  +    catch
  +        throw:{error, Output} ->
  +            {error, unicode:characters_to_binary(Output)};
  +        C:E:Stk ->
  +            {crash, {C,E,Stk}}
  +    end.
  +
  +%% Run the the compiler in a separate process.
  +compile_cmdline1(Args) ->
  +    {ok, Cwd} = file:get_cwd(),
  +    {Pid,Ref} = spawn_monitor(fun() -> exit(compile(Args, Cwd)) end),
       receive
  -	{'EXIT', Pid, {compiler_result, Result}} ->
  -	    Result;
  -	{'EXIT', Pid, {compiler_error, Error}} ->
  -	    io:put_chars(?STDERR, Error),
  -	    io:nl(?STDERR),
  -	    error;
  -	{'EXIT', Pid, Reason} ->
  -	    io:format(?STDERR, "Runtime error: ~tp~n", [Reason]),
  -	    error
  -    end.
  -
  --spec compiler_runner([cmd_line_arg()]) -> fun(() -> no_return()).
  -
  -compiler_runner(List) ->
  -    fun() ->
  -            %% We don't want the current directory in the code path.
  -            %% Remove it.
  -            Path = [D || D <- code:get_path(), D =/= "."],
  -            true = code:set_path(Path),
  -            exit({compiler_result, compile1(List)})
  -    end.
  -
  -%% Parses the first part of the option list.
  -
  -compile1(Args) ->
  -    {ok, Cwd} = file:get_cwd(),
  -    compile1(Args, #options{outdir=Cwd,cwd=Cwd}).
  -
  -%% Parses all options.
  -
  +        {'DOWN', Ref, process, Pid, Result} ->
  +            case Result of
  +                ok ->
  +                    halt(0);
  +                {error, Output} ->
  +                    io:put_chars(standard_error, Output),
  +                    halt(1);
  +                {crash, {C,E,Stk}} ->
  +                    io:format(standard_error, "Crash: ~p:~tp\n~tp\n",
  +                              [C,E,Stk]),
  +                    halt(2)
  +            end
  +    end.
  +
  +cmdline_init() ->
  +    %% We don't want the current directory in the code path.
  +    %% Remove it.
  +    Path = [D || D <- code:get_path(), D =/= "."],
  +    true = code:set_path(Path),
  +    ok.
  +
  +%% Parse all options.
   compile1(["--"|Files], Opts) ->
       compile2(Files, Opts);
   compile1(["-"++Option|T], Opts) ->
  
positive.code:     {Target,T} = get_option("MT", Opt, T0),
      {[{makedep_target,Target}],T};
  parse_dep_option(Opt, _T) ->
      io:format(?STDERR, "Unknown option: -M~ts\n", [Opt]),
      usage().
  
  usage() ->
      H = [{"-b type","type of output file (e.g. beam)"},
  	 {"-d","turn on debugging of erlc itself"},
  	 {"-Dname","define name"},
  
negative.code: 	 {"-S","generate assembly listing (Erlang compiler)"},
  	 {"-P","generate listing of preprocessed code (Erlang compiler)"},
  	 {"+term","pass the Erlang term unchanged to the compiler"}],
      Msg = [Error,
             "Usage: erlc [Options] file.ext ...\n",
             "Options:\n",
             [io_lib:format("~-14s ~s\n", [K,D]) || {K,D} <- H]],
      throw({error, Msg}).
  
  get_option(_Name, [], [[C|_]=Option|T]) when C =/= $- ->
      {Option,T};
  get_option(_Name, [_|_]=Option, T) ->
      {Option,T};
  get_option(Name, _, _) ->
      throw({error, "No value given to -"++Name++" option\n"}).
  
  split_at_equals([$=|T], Acc) ->
      {lists:reverse(Acc),T};
  