diff --git a/erlang/apps/as/priv/test6.s b/erlang/apps/as/priv/test6.s new file mode 100644 index 0000000..4c09155 --- /dev/null +++ b/erlang/apps/as/priv/test6.s @@ -0,0 +1,23 @@ +/* + * test6.s + * Copyright (C) 2019 Mikael Pettersson + * + * This file is part of pdp10-tools. + * + * pdp10-tools is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pdp10-tools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pdp10-tools. If not, see . + */ + + .text + .ascii "bar" + .asciz "foo", "fie", "fum" diff --git a/erlang/apps/as/src/assemble.erl b/erlang/apps/as/src/assemble.erl index 17807e9..815b322 100644 --- a/erlang/apps/as/src/assemble.erl +++ b/erlang/apps/as/src/assemble.erl @@ -100,12 +100,21 @@ stmts_image([Stmt | Stmts], Tunit, Acc) -> stmt_image(Stmt, Tunit) -> case Stmt of + #s_dot_ascii{} -> dot_ascii_image(Stmt, Tunit); #s_dot_byte{} -> dot_byte_image(Stmt, Tunit); #s_dot_long{} -> dot_long_image(Stmt, Tunit); #s_dot_short{} -> dot_short_image(Stmt, Tunit); #s_insn{} -> insn_image(Stmt, Tunit) end. +dot_ascii_image(#s_dot_ascii{z = Z, strings = Strings}, _Tunit) -> + Image = + case Z of + true -> [String ++ [0] || String <- Strings]; + false -> Strings + end, + {ok, Image}. + dot_byte_image(#s_dot_byte{exprs = Exprs}, Tunit) -> integer_data_directive(Exprs, Tunit, fun(Value) -> Value band ?PDP10_UINT9_MAX end). diff --git a/erlang/apps/as/src/input.erl b/erlang/apps/as/src/input.erl index d2389cc..5c1c8c3 100644 --- a/erlang/apps/as/src/input.erl +++ b/erlang/apps/as/src/input.erl @@ -313,6 +313,7 @@ pass2_stmts([{Location, Stmt} | Stmts], Tunit) -> pass2_stmt(Location, Tunit, Stmt) -> case Stmt of + #s_dot_ascii{} -> dot_ascii(Location, Tunit, Stmt); #s_dot_byte{} -> dot_byte(Location, Tunit, Stmt); #s_dot_file{} -> dot_file(Location, Tunit, Stmt); #s_dot_globl{} -> dot_globl(Location, Tunit, Stmt); @@ -326,6 +327,21 @@ pass2_stmt(Location, Tunit, Stmt) -> #s_insn{} -> insn(Location, Tunit, Stmt) end. +dot_ascii(_Location, Tunit, #s_dot_ascii{z = Z, strings = Strings} = Stmt) -> + #tunit{cursect = Cursect} = Tunit, + #section{data = {stmts, Stmts}, dot = Dot} = Section = tunit:get_section(Tunit, Cursect), + Size0 = lists:sum(lists:map(fun erlang:length/1, Strings)), + Size = + case Z of + true -> Size0 + length(Strings); + false -> Size0 + end, + NewSection = + Section#section{ data = {stmts, [Stmt | Stmts]} + , dot = Dot + Size + }, + {ok, tunit:put_section(Tunit, NewSection)}. + dot_byte(Location, Tunit, #s_dot_byte{} = Stmt0) -> integer_data_directive(Location, Tunit, Stmt0, 1, ".byte", fun(Stmt) -> Stmt#s_dot_byte.exprs end, diff --git a/erlang/apps/as/src/parse.erl b/erlang/apps/as/src/parse.erl index d0cd659..4fc217e 100644 --- a/erlang/apps/as/src/parse.erl +++ b/erlang/apps/as/src/parse.erl @@ -34,6 +34,8 @@ -> {ok, {location(), stmt()}} | eof | {error, {module(), term()}}. stmt(ScanState) -> case scan:token(ScanState) of + {ok, {Location, ?T_DOT_ASCII}} -> dot_ascii(ScanState, Location); + {ok, {Location, ?T_DOT_ASCIZ}} -> dot_asciz(ScanState, Location); {ok, {Location, ?T_DOT_BYTE}} -> dot_byte(ScanState, Location); {ok, {Location, ?T_DOT_DATA}} -> dot_data(ScanState, Location); {ok, {Location, ?T_DOT_FILE}} -> dot_file(ScanState, Location); @@ -274,6 +276,23 @@ badinsn(Location, Fmt, Mnemonic) -> %% Directives ------------------------------------------------------------------ +dot_ascii(ScanState, Location) -> + dot_ascii(ScanState, Location, ".ascii", _Z = false). + +dot_asciz(ScanState, Location) -> + dot_ascii(ScanState, Location, ".asciz", _Z = true). + +dot_ascii(ScanState, Location, Lexeme, Z) -> + case string_list(ScanState) of + {ok, {Strings, Follow}} -> + case Follow of + {_Location, ?T_NEWLINE} -> + {ok, {Location, #s_dot_ascii{z = Z, strings = Strings}}}; + _ -> badtok("junk after " ++ Lexeme ++ " ", {ok, Follow}) + end; + {error, _Reason} = Error -> Error + end. + dot_byte(ScanState, Location) -> integer_data_directive(ScanState, Location, ".byte", fun(Exprs) -> #s_dot_byte{exprs = Exprs} end). @@ -500,6 +519,29 @@ expr_opt(ScanState) -> Error end. +%% String Lists ---------------------------------------------------------------- + +%% ::= ( ("," )*)? +string_list(ScanState) -> + case scan:token(ScanState) of + {ok, {_Location, {?T_STRING, String}}} -> string_list(ScanState, [String]); + {ok, Follow} -> {ok, {[], Follow}}; + {error, _Reason} = Error -> Error + end. + +string_list(ScanState, Strings) -> + case scan:token(ScanState) of + {ok, {_Location1, ?T_COMMA}} -> + case scan:token(ScanState) of + {ok, {_Location2, {?T_STRING, String}}} -> + string_list(ScanState, [String | Strings]); + {ok, First} -> badtok("expected string literal", {ok, First}); + {error, _Reason} = Error -> Error + end; + {ok, Follow} -> {ok, {lists:reverse(Strings), Follow}}; + {error, _Reason} = Error -> Error + end. + %% Error reporting ------------------------------------------------------------- badtok(_ErrMsg, {error, _Reason} = Error) -> Error; diff --git a/erlang/apps/as/src/token.erl b/erlang/apps/as/src/token.erl index 3ecc880..8506cd5 100644 --- a/erlang/apps/as/src/token.erl +++ b/erlang/apps/as/src/token.erl @@ -29,6 +29,8 @@ -spec from_symbol(string()) -> token(). from_symbol(Name) -> case Name of + ".ascii" -> ?T_DOT_ASCII; + ".asciz" -> ?T_DOT_ASCIZ; ".byte" -> ?T_DOT_BYTE; ".data" -> ?T_DOT_DATA; ".file" -> ?T_DOT_FILE; @@ -51,6 +53,8 @@ from_symbol(Name) -> -spec format(token()) -> io_lib:chars(). format(Token) -> case Token of + ?T_DOT_ASCII -> ".ascii"; + ?T_DOT_ASCIZ -> ".asciz"; ?T_DOT_BYTE -> ".byte"; ?T_DOT_DATA -> ".data"; ?T_DOT_FILE -> ".file"; diff --git a/erlang/apps/as/src/token.hrl b/erlang/apps/as/src/token.hrl index 23553e9..1a3da82 100644 --- a/erlang/apps/as/src/token.hrl +++ b/erlang/apps/as/src/token.hrl @@ -26,6 +26,8 @@ %% with attributes (ordinary symbols, literals, errors). %% reserved symbols including directives +-define(T_DOT_ASCII, 'T_DOT_ASCII'). % .ascii +-define(T_DOT_ASCIZ, 'T_DOT_ASCIZ'). % .asciz -define(T_DOT_BYTE, 'T_DOT_BYTE'). % .byte -define(T_DOT_DATA, 'T_DOT_DATA'). % .data -define(T_DOT_FILE, 'T_DOT_FILE'). % .file @@ -64,7 +66,9 @@ -define(T_NEWLINE, 'T_NEWLINE'). % -define(T_EOF, 'T_EOF'). % --type token() :: ?T_DOT_BYTE +-type token() :: ?T_DOT_ASCII + | ?T_DOT_ASCIZ + | ?T_DOT_BYTE | ?T_DOT_DATA | ?T_DOT_FILE | ?T_DOT_GLOBL diff --git a/erlang/apps/as/src/tunit.hrl b/erlang/apps/as/src/tunit.hrl index 19b5cb7..64fc667 100644 --- a/erlang/apps/as/src/tunit.hrl +++ b/erlang/apps/as/src/tunit.hrl @@ -36,6 +36,9 @@ %% either interpreted immediately or appended to the representation of the %% current section. +%% .asci{i,z} [string (, string)*] +-record(s_dot_ascii, {z :: boolean(), strings :: [string()]}). + %% .byte [expr (, expr)*] -record(s_dot_byte, {exprs :: [expr()]}). @@ -90,7 +93,8 @@ , index :: 0..((1 bsl 4) - 1) }). --type stmt() :: #s_dot_data{} +-type stmt() :: #s_dot_ascii{} + | #s_dot_data{} | #s_dot_file{} | #s_dot_globl{} | #s_dot_ident{}