anchor.diff:                          gpb_parse:absolutify_names(Defs1))),
               case gpb_parse:verify_refs(Defs2) of
                   ok ->
  -                    gpb_parse:normalize_msg_field_options( %% Sort it?
  -                      gpb_parse:enumerate_msg_fields(
  -                        gpb_parse:extend_msgs(
  -                          gpb_parse:resolve_refs(Defs2))))
  +                    {ok, gpb_parse:normalize_msg_field_options( %% Sort it?
  +                           gpb_parse:enumerate_msg_fields(
  +                             gpb_parse:extend_msgs(
  +                               gpb_parse:resolve_refs(Defs2))))};
  +                {error, _Reason} = Error ->
  +                    Error
               end;
           {error, Reason} ->
               {error, Reason}
       end.
   
  -parse_file_and_imports(FName) ->
  -    parse_file_and_imports(FName, [FName]).
  -
  -parse_file_and_imports(FName, AlreadyImported) ->
  -    FName2 = locate_import(FName),
  -    {ok,B} = file:read_file(FName2),
  -    %% Add to AlreadyImported to prevent trying to import it again: in
  -    %% case we get an error we don't want to try to reprocess it later
  -    %% (in case it is multiply imported) and get the error again.
  -    AlreadyImported2 = [FName | AlreadyImported],
  -    case scan_and_parse_string(binary_to_list(B)) of
  -        {ok, Defs} ->
  -            Imports = gpb_parse:fetch_imports(Defs),
  -            {ok, lists:foldl(
  -                   fun(Import, {Ds,Is}) ->
  -                           case lists:member(Import, Is) of
  -                               true  -> {Ds,Is};
  -                               false -> import_it(Import, Ds, Is)
  -                           end
  -                   end,
  -                   {Defs, AlreadyImported2},
  -                   Imports)};
  +parse_file_and_imports(FName, Opts) ->
  +    parse_file_and_imports(FName, [FName], Opts).
  +
  +parse_file_and_imports(FName, AlreadyImported, Opts) ->
  +    case locate_import(FName, Opts) of
  +        {ok, FName2} ->
  +            {ok,B} = file:read_file(FName2),
  +            %% Add to AlreadyImported to prevent trying to import it again: in
  +            %% case we get an error we don't want to try to reprocess it later
  +            %% (in case it is multiply imported) and get the error again.
  +            AlreadyImported2 = [FName | AlreadyImported],
  +            case scan_and_parse_string(binary_to_list(B)) of
  +                {ok, Defs} ->
  +                    Imports = gpb_parse:fetch_imports(Defs),
  +                    read_and_parse_imports(Imports,AlreadyImported2,Defs,Opts);
  +                {error, Reason} ->
  +                    {error, Reason}
  +            end;
           {error, Reason} ->
  -            io:format("Error for ~s (ignoring):~n  ~p~n",
  -                      [FName, Reason]),
               {error, Reason}
       end.
   
  
positive.code:             case gpb_parse:parse(Tokens++[{'$end', 999}]) of
                  {ok, Result} ->
                      {ok, Result};
                  {error, {LNum,_Module,EMsg}=Reason} ->
                      io:format(user, "Parse error on line ~w:~n  ~p~n",
                                [LNum, {Tokens,EMsg}]),
                      erlang:error({parse_error,S,Reason})
              end;
          {error,Reason} ->
              io:format(user, "Scan error:~n  ~p~n", [Reason]),
              erlang:error({scan_error,S,Reason})
      end.
  
  
  import_it(Import, Defs, AlreadyImported) ->
      %% FIXME: how do we handle scope of declarations,
      %%        e.g. options/package for imported files?
      case parse_file_and_imports(Import, AlreadyImported) of
          {ok, {MoreDefs, MoreImported}} ->
              Defs2 = Defs++MoreDefs,
              Imported2 = lists:usort(AlreadyImported++MoreImported),
              {Defs2, Imported2};
          {error, Reason} ->
              io:format("Error for ~s (ignoring):~n  ~p~n", [Import, Reason]),
              {Defs, AlreadyImported}
      end.
  
  locate_import(Import) -> "/tmp/u/"++Import. %% FIXME: include path...
  
  format_erl(Mod, Defs) ->
      iolist_to_binary(
  
negative.code: 
  -module(gpb_compile).
  %-compile(export_all).
  -export([file/1, file/2]).
  -include_lib("kernel/include/file.hrl").
  -include_lib("eunit/include/eunit.hrl").
  -include("gpb.hrl").
  
  %% @spec file(File) -> ok | {error, Reason}
  %% @equiv file(File, [])
  file(File) ->
      file(File, []).
  
  %% @spec file(File) -> ok | {error, Reason}
  %%            File = string()
  %%            Opts = [Opt]
  %%            Opt  = {i,directory()}
  file(File, Opts) ->
      case parse_file(File, Opts) of
          {ok, Defs} ->
              Ext = filename:extension(File),
              Mod = list_to_atom(filename:basename(File, Ext)),
              Erl = change_ext(File, ".erl"),
              Hrl = change_ext(File, ".hrl"),
              file:write_file(Erl, format_erl(Mod, Defs)),
              file:write_file(Hrl, format_hrl(Mod, Defs));
          {error, _Reason} = Error ->
              Error
      end.
  
  change_ext(File, NewExt) ->
      filename:join(filename:dirname(File),
                    filename:basename(File, filename:extension(File)) ++ NewExt).
  
  parse_file(FName, Opts) ->
      case parse_file_and_imports(FName, Opts) of
          {ok, {Defs1, _AllImported}} ->
              %% io:format("processed these imports:~n  ~p~n", [_AllImported]),
              %% io:format("Defs1=~n  ~p~n", [Defs1]),
  