mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-05-04 15:06:36 +00:00
as: convert to module-tagged errors, format_error/1, and error:format/1; improve specs
This commit is contained in:
@@ -36,8 +36,8 @@ main_(Argv) ->
|
|||||||
ok -> halt(0);
|
ok -> halt(0);
|
||||||
{error, _Reason} = Error -> escript_runtime:fatal("~p\n", [Error])
|
{error, _Reason} = Error -> escript_runtime:fatal("~p\n", [Error])
|
||||||
end;
|
end;
|
||||||
{error, ErrMsg} ->
|
{error, Reason} ->
|
||||||
escript_runtime:errmsg("~s\n", [ErrMsg]),
|
escript_runtime:errmsg("~s\n", [error:format(Reason)]),
|
||||||
usage()
|
usage()
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,13 @@
|
|||||||
-module(assemble).
|
-module(assemble).
|
||||||
|
|
||||||
-export([ tunit/1
|
-export([ tunit/1
|
||||||
|
, format_error/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("tunit.hrl").
|
-include("tunit.hrl").
|
||||||
-include_lib("lib/include/pdp10_elf36.hrl").
|
-include_lib("lib/include/pdp10_elf36.hrl").
|
||||||
|
|
||||||
|
-spec tunit(#tunit{}) -> {ok, #tunit{}} | {error, {module(), term()}}.
|
||||||
tunit(Tunit) ->
|
tunit(Tunit) ->
|
||||||
sections(maps:values(Tunit#tunit.sections), Tunit).
|
sections(maps:values(Tunit#tunit.sections), Tunit).
|
||||||
|
|
||||||
@@ -47,7 +49,7 @@ section(Section, Tunit) ->
|
|||||||
, sh_flags = ?SHF_MERGE bor ?SHF_STRINGS
|
, sh_flags = ?SHF_MERGE bor ?SHF_STRINGS
|
||||||
} -> comment(Section, Tunit);
|
} -> comment(Section, Tunit);
|
||||||
#section{ name = Name } ->
|
#section{ name = Name } ->
|
||||||
{error, io_lib:format("don't know how to assemble section ~s", [Name])}
|
{error, {?MODULE, {cannot_assemble, Name}}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% Assemble .comment -----------------------------------------------------------
|
%% Assemble .comment -----------------------------------------------------------
|
||||||
@@ -100,3 +102,9 @@ insn_image(Insn) ->
|
|||||||
(Word bsr 18) band 511,
|
(Word bsr 18) band 511,
|
||||||
(Word bsr 9) band 511,
|
(Word bsr 9) band 511,
|
||||||
Word band 511].
|
Word band 511].
|
||||||
|
|
||||||
|
%% Error reporting -------------------------------------------------------------
|
||||||
|
|
||||||
|
-spec format_error(term()) -> io_lib:chars().
|
||||||
|
format_error({cannot_assemble, Name}) ->
|
||||||
|
io_lib:format("don't know how to assemble section ~s", [Name]).
|
||||||
|
|||||||
@@ -21,11 +21,13 @@
|
|||||||
-module(input).
|
-module(input).
|
||||||
|
|
||||||
-export([ files/1
|
-export([ files/1
|
||||||
|
, format_error/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("tunit.hrl").
|
-include("tunit.hrl").
|
||||||
-include_lib("lib/include/pdp10_elf36.hrl").
|
-include_lib("lib/include/pdp10_elf36.hrl").
|
||||||
|
|
||||||
|
-spec files([string()]) -> {ok, #tunit{}} | {error, {module(), term()}}.
|
||||||
files(Files) ->
|
files(Files) ->
|
||||||
NewFiles =
|
NewFiles =
|
||||||
case Files of
|
case Files of
|
||||||
@@ -235,9 +237,11 @@ section_dot_text() -> % ".text"
|
|||||||
|
|
||||||
%% Error reporting -------------------------------------------------------------
|
%% Error reporting -------------------------------------------------------------
|
||||||
|
|
||||||
%% FIXME: this is duplicated a few times, move it to scan_state.erl
|
|
||||||
fmterr(ScanState, Fmt, Args) ->
|
fmterr(ScanState, Fmt, Args) ->
|
||||||
{ok, FileName} = scan_state:filename(ScanState),
|
{ok, FileName} = scan_state:filename(ScanState),
|
||||||
{ok, LineNr} = scan_state:linenr(ScanState),
|
{ok, LineNr} = scan_state:linenr(ScanState),
|
||||||
{error, lists:flatten(io_lib:format("file ~s line ~p: " ++ Fmt,
|
{error, {?MODULE, {FileName, LineNr, Fmt, Args}}}.
|
||||||
[FileName, LineNr | Args]))}.
|
|
||||||
|
-spec format_error(term()) -> io_lib:chars().
|
||||||
|
format_error({FileName, LineNr, Fmt, Args}) ->
|
||||||
|
io_lib:format("file ~s line ~p: " ++ Fmt, [FileName, LineNr | Args]).
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
-module(output).
|
-module(output).
|
||||||
|
|
||||||
-export([ tunit/2
|
-export([ tunit/2
|
||||||
|
, format_error/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("tunit.hrl").
|
-include("tunit.hrl").
|
||||||
@@ -64,6 +65,7 @@
|
|||||||
, strtab :: #strtab{}
|
, strtab :: #strtab{}
|
||||||
}).
|
}).
|
||||||
|
|
||||||
|
-spec tunit(#tunit{}, string()) -> ok | {error, {module(), term()}}.
|
||||||
tunit(Tunit, File) ->
|
tunit(Tunit, File) ->
|
||||||
emit(layout(Tunit), File).
|
emit(layout(Tunit), File).
|
||||||
|
|
||||||
@@ -330,7 +332,7 @@ emit(Context, File) ->
|
|||||||
emit(Funs, Context, FP, 0)
|
emit(Funs, Context, FP, 0)
|
||||||
after pdp10_stdio:fclose(FP)
|
after pdp10_stdio:fclose(FP)
|
||||||
end;
|
end;
|
||||||
{error, Reason} -> {error, io_lib:format("opening ~s: ~p", [File, Reason])}
|
{error, Reason} -> {error, {?MODULE, {cannot_open, File, Reason}}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
emit([], _Context, _FP, _Offset) -> ok;
|
emit([], _Context, _FP, _Offset) -> ok;
|
||||||
@@ -558,3 +560,9 @@ image_write([H | T], FP) ->
|
|||||||
image_write([], _FP) -> ok;
|
image_write([], _FP) -> ok;
|
||||||
image_write(TByte, FP) when is_integer(TByte), 0 =< TByte, TByte =< 511 ->
|
image_write(TByte, FP) when is_integer(TByte), 0 =< TByte, TByte =< 511 ->
|
||||||
pdp10_stdio:fputc(TByte, FP).
|
pdp10_stdio:fputc(TByte, FP).
|
||||||
|
|
||||||
|
%% Error reporting -------------------------------------------------------------
|
||||||
|
|
||||||
|
-spec format_error(term()) -> io_lib:chars().
|
||||||
|
format_error({cannot_open, File, Reason}) ->
|
||||||
|
io_lib:format("opening ~s: ~s", [File, error:format(Reason)]).
|
||||||
|
|||||||
@@ -21,12 +21,15 @@
|
|||||||
-module(parse).
|
-module(parse).
|
||||||
|
|
||||||
-export([ stmt/1
|
-export([ stmt/1
|
||||||
|
, format_error/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("token.hrl").
|
-include("token.hrl").
|
||||||
-include("tunit.hrl").
|
-include("tunit.hrl").
|
||||||
-include_lib("lib/include/pdp10_opcodes.hrl").
|
-include_lib("lib/include/pdp10_opcodes.hrl").
|
||||||
|
|
||||||
|
-spec stmt(scan_state:scan_state())
|
||||||
|
-> {ok, stmt()} | eof | {error, {module(), term()}}.
|
||||||
stmt(ScanState) ->
|
stmt(ScanState) ->
|
||||||
case scan:token(ScanState) of
|
case scan:token(ScanState) of
|
||||||
{ok, ?T_DOT_FILE} -> dot_file(ScanState);
|
{ok, ?T_DOT_FILE} -> dot_file(ScanState);
|
||||||
@@ -303,10 +306,13 @@ dot_type(ScanState) ->
|
|||||||
|
|
||||||
badtok(_ScanState, _ErrMsg, {error, _Reason} = Error) -> Error;
|
badtok(_ScanState, _ErrMsg, {error, _Reason} = Error) -> Error;
|
||||||
badtok(ScanState, ErrMsg, {ok, Token}) ->
|
badtok(ScanState, ErrMsg, {ok, Token}) ->
|
||||||
fmterr(ScanState, ErrMsg ++ "; current token is ~s", [token:to_string(Token)]).
|
fmterr(ScanState, ErrMsg ++ "; current token is ~s", [token:format(Token)]).
|
||||||
|
|
||||||
fmterr(ScanState, Fmt, Args) ->
|
fmterr(ScanState, Fmt, Args) ->
|
||||||
{ok, FileName} = scan_state:filename(ScanState),
|
{ok, FileName} = scan_state:filename(ScanState),
|
||||||
{ok, LineNr} = scan_state:linenr(ScanState),
|
{ok, LineNr} = scan_state:linenr(ScanState),
|
||||||
{error, lists:flatten(io_lib:format("file ~s line ~p: " ++ Fmt,
|
{error, {?MODULE, {FileName, LineNr, Fmt, Args}}}.
|
||||||
[FileName, LineNr | Args]))}.
|
|
||||||
|
-spec format_error(term()) -> io_lib:chars().
|
||||||
|
format_error({FileName, LineNr, Fmt, Args}) ->
|
||||||
|
io_lib:format("file ~s line ~p: " ++ Fmt, [FileName, LineNr | Args]).
|
||||||
|
|||||||
@@ -21,10 +21,13 @@
|
|||||||
-module(scan).
|
-module(scan).
|
||||||
|
|
||||||
-export([ token/1
|
-export([ token/1
|
||||||
|
, format_error/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("token.hrl").
|
-include("token.hrl").
|
||||||
|
|
||||||
|
-spec token(scan_state:scan_state())
|
||||||
|
-> {ok, token()} | {error, {module(), term()}}.
|
||||||
token(ScanState) ->
|
token(ScanState) ->
|
||||||
case scan_state:fgetc(ScanState) of
|
case scan_state:fgetc(ScanState) of
|
||||||
{error, _Reason} = Error -> Error;
|
{error, _Reason} = Error -> Error;
|
||||||
@@ -220,11 +223,14 @@ chval(Ch) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
badchar(ScanState, Ch, Context) ->
|
badchar(ScanState, Ch, Context) ->
|
||||||
ChStr = char_to_string(Ch),
|
|
||||||
{ok, FileName} = scan_state:filename(ScanState),
|
{ok, FileName} = scan_state:filename(ScanState),
|
||||||
{ok, LineNr} = scan_state:linenr(ScanState),
|
{ok, LineNr} = scan_state:linenr(ScanState),
|
||||||
{error, lists:flatten(io_lib:format("~s line ~p: invalid character '~s' ~s",
|
{error, {?MODULE, {FileName, LineNr, Ch, Context}}}.
|
||||||
[FileName, LineNr, ChStr, Context]))}.
|
|
||||||
|
-spec format_error(term()) -> io_lib:chars().
|
||||||
|
format_error({FileName, LineNr, Ch, Context}) ->
|
||||||
|
io_lib:format("~s line ~p: invalid character '~s' ~s",
|
||||||
|
[FileName, LineNr, char_to_string(Ch), Context]).
|
||||||
|
|
||||||
char_to_string(eof) -> "<EOF>";
|
char_to_string(eof) -> "<EOF>";
|
||||||
char_to_string(Ch) when $\s =< Ch, Ch =< $~ -> [$', Ch, $'];
|
char_to_string(Ch) when $\s =< Ch, Ch =< $~ -> [$', Ch, $'];
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
% meta-data accessors
|
% meta-data accessors
|
||||||
, filename/1
|
, filename/1
|
||||||
, linenr/1
|
, linenr/1
|
||||||
|
, format_error/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
@@ -52,39 +53,54 @@
|
|||||||
, linenr :: pos_integer()
|
, linenr :: pos_integer()
|
||||||
}).
|
}).
|
||||||
|
|
||||||
|
-type scan_state() :: pid().
|
||||||
|
|
||||||
|
-export_type([scan_state/0]).
|
||||||
|
|
||||||
%% API -------------------------------------------------------------------------
|
%% API -------------------------------------------------------------------------
|
||||||
|
|
||||||
-spec fclose(pid()) -> ok | {error, any()}.
|
-spec fclose(scan_state()) -> ok | {error, {module(), term()}}.
|
||||||
fclose(Pid) ->
|
fclose(Pid) ->
|
||||||
gen_server:call(Pid, fclose, infinity).
|
gen_server:call(Pid, fclose, infinity).
|
||||||
|
|
||||||
-spec fgetc(pid()) -> {ok, byte()} | eof | {error, any()}.
|
-spec fgetc(scan_state()) -> {ok, byte()} | eof | {error, {module(), term()}}.
|
||||||
fgetc(Pid) ->
|
fgetc(Pid) ->
|
||||||
gen_server:call(Pid, fgetc, infinity).
|
gen_server:call(Pid, fgetc, infinity).
|
||||||
|
|
||||||
-spec fopen(string()) -> {ok, pid()} | {error, any()}.
|
-spec fopen(string()) -> {ok, scan_state()} | {error, {module(), term()}}.
|
||||||
fopen(File) ->
|
fopen(File) ->
|
||||||
do_fopen(File).
|
do_fopen(File).
|
||||||
|
|
||||||
-spec stdin() -> {ok, pid()}.
|
-spec stdin() -> {ok, scan_state()}.
|
||||||
stdin() ->
|
stdin() ->
|
||||||
do_fopen(stdin).
|
do_fopen(stdin).
|
||||||
|
|
||||||
do_fopen(File) ->
|
do_fopen(File) ->
|
||||||
gen_server:start(?MODULE, File, []).
|
gen_server:start(?MODULE, File, []).
|
||||||
|
|
||||||
-spec ungetc(byte(), pid()) -> ok | {error, any()}.
|
-spec ungetc(byte(), scan_state()) -> ok | {error, {module(), term()}}.
|
||||||
ungetc(Ch, Pid) ->
|
ungetc(Ch, Pid) ->
|
||||||
gen_server:call(Pid, {ungetc, Ch}, infinity).
|
gen_server:call(Pid, {ungetc, Ch}, infinity).
|
||||||
|
|
||||||
-spec filename(pid()) -> {ok, string()}.
|
-spec filename(scan_state()) -> {ok, string()}.
|
||||||
filename(Pid) ->
|
filename(Pid) ->
|
||||||
gen_server:call(Pid, filename, infinity).
|
gen_server:call(Pid, filename, infinity).
|
||||||
|
|
||||||
-spec linenr(pid()) -> {ok, pos_integer()}.
|
-spec linenr(scan_state()) -> {ok, pos_integer()}.
|
||||||
linenr(Pid) ->
|
linenr(Pid) ->
|
||||||
gen_server:call(Pid, linenr, infinity).
|
gen_server:call(Pid, linenr, infinity).
|
||||||
|
|
||||||
|
-spec format_error(term()) -> io_lib:chars().
|
||||||
|
format_error(Reason) ->
|
||||||
|
case Reason of
|
||||||
|
{bad_request, Req} ->
|
||||||
|
io_lib:format("internal error: bad request: ~p", [Req]);
|
||||||
|
ungetc ->
|
||||||
|
"internal error: invalid ungetc";
|
||||||
|
_ ->
|
||||||
|
io_lib:format("~p", [Reason])
|
||||||
|
end.
|
||||||
|
|
||||||
%% gen_server callbacks --------------------------------------------------------
|
%% gen_server callbacks --------------------------------------------------------
|
||||||
|
|
||||||
init(stdin) ->
|
init(stdin) ->
|
||||||
@@ -92,7 +108,7 @@ init(stdin) ->
|
|||||||
init(File) ->
|
init(File) ->
|
||||||
case file:open(File, [raw, read, read_ahead]) of
|
case file:open(File, [raw, read, read_ahead]) of
|
||||||
{ok, IoDev} -> do_init(File, IoDev);
|
{ok, IoDev} -> do_init(File, IoDev);
|
||||||
{error, Reason} -> {stop, Reason}
|
{error, Reason} -> {stop, {file, Reason}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_init(FileName, IoDev) ->
|
do_init(FileName, IoDev) ->
|
||||||
@@ -115,7 +131,7 @@ handle_call(Req, _From, State) ->
|
|||||||
linenr ->
|
linenr ->
|
||||||
{reply, {ok, State#state.linenr}, State};
|
{reply, {ok, State#state.linenr}, State};
|
||||||
_ ->
|
_ ->
|
||||||
{reply, {error, {bad_request, Req}}, State}
|
{reply, {error, {?MODULE, {bad_request, Req}}}, State}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
handle_cast(_Req, State) ->
|
handle_cast(_Req, State) ->
|
||||||
@@ -155,7 +171,7 @@ handle_fgetc(State) ->
|
|||||||
_ -> State
|
_ -> State
|
||||||
end};
|
end};
|
||||||
eof -> {eof, State};
|
eof -> {eof, State};
|
||||||
{error, _Reason} = Error -> {Error, State}
|
{error, Reason} -> {{error, {file, Reason}}, State}
|
||||||
end,
|
end,
|
||||||
{reply, Result, NewState};
|
{reply, Result, NewState};
|
||||||
Ch ->
|
Ch ->
|
||||||
@@ -167,5 +183,5 @@ handle_fgetc(State) ->
|
|||||||
handle_ungetc(State, Ch) ->
|
handle_ungetc(State, Ch) ->
|
||||||
case State#state.ungetc of
|
case State#state.ungetc of
|
||||||
[] -> {reply, ok, State#state{ungetc = Ch}};
|
[] -> {reply, ok, State#state{ungetc = Ch}};
|
||||||
_ -> {reply, {error, ungetc}, State}
|
_ -> {reply, {error, {?MODULE, ungetc}}, State}
|
||||||
end.
|
end.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
-module(token).
|
-module(token).
|
||||||
|
|
||||||
-export([ from_symbol/1
|
-export([ from_symbol/1
|
||||||
, to_string/1
|
, format/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("token.hrl").
|
-include("token.hrl").
|
||||||
@@ -38,8 +38,8 @@ from_symbol(Name) ->
|
|||||||
_ -> {?T_SYMBOL, Name}
|
_ -> {?T_SYMBOL, Name}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec to_string(token()) -> string().
|
-spec format(token()) -> io_lib:chars().
|
||||||
to_string(Token) ->
|
format(Token) ->
|
||||||
case Token of
|
case Token of
|
||||||
?T_DOT_FILE -> ".file";
|
?T_DOT_FILE -> ".file";
|
||||||
?T_DOT_GLOBL -> ".globl";
|
?T_DOT_GLOBL -> ".globl";
|
||||||
|
|||||||
Reference in New Issue
Block a user