mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-01-24 11:22:52 +00:00
as: handle .ascii and .asciz directives
This commit is contained in:
parent
9f51730200
commit
72df4dc2b3
23
erlang/apps/as/priv/test6.s
Normal file
23
erlang/apps/as/priv/test6.s
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.text
|
||||
.ascii "bar"
|
||||
.asciz "foo", "fie", "fum"
|
||||
@ -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).
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 ++ " <strings>", {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> ::= (<string> ("," <string>)*)?
|
||||
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;
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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'). % <end-of-line>
|
||||
-define(T_EOF, 'T_EOF'). % <end-of-file>
|
||||
|
||||
-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
|
||||
|
||||
@ -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{}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user