Skip to content

Commit

Permalink
Disable EQUS expansion for raw symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
Rangi42 committed Feb 5, 2025
1 parent d9d381c commit 2cf28a7
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 15 deletions.
6 changes: 5 additions & 1 deletion man/rgbasm.5
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,9 @@ Additionally, label names can contain up to a single dot
.Ql \&. ,
which may not be the first character.
.Pp
A symbol cannot have the same name as a reserved keyword, unless it is prefixed by a hash
A symbol cannot have the same name as a reserved keyword, unless it is a
.Dq raw symbol
prefixed by a hash
.Sq # .
For example,
.Ql #load
Expand Down Expand Up @@ -1387,6 +1389,8 @@ This expansion is disabled in a few contexts:
and
.Ql MACRO name
will not expand string constants in their names.
Expansion is also disabled for raw string constant symbols (string constant symbols prefixed by a hash
.Sq # ) .
.Bd -literal -offset indent
DEF COUNTREG EQUS "[hl+]"
ld a, COUNTREG
Expand Down
4 changes: 2 additions & 2 deletions src/asm/lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1910,8 +1910,8 @@ static Token yylex_NORMAL() {
// `token` is either an `ID` or a `LOCAL_ID`, and both have a `std::string` value.
assume(token.value.holds<std::string>());

// Local symbols cannot be string expansions
if (token.type == T_(ID) && lexerState->expandStrings) {
// Raw symbols and local symbols cannot be string expansions
if (!raw && token.type == T_(ID) && lexerState->expandStrings) {
// Attempt string expansion
Symbol const *sym = sym_FindExactSymbol(token.value.get<std::string>());

Expand Down
90 changes: 78 additions & 12 deletions src/asm/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@

// Strings
%type <std::string> string
%type <std::string> string_literal
%type <std::string> strcat_args
// Strings used for identifiers
%type <std::string> def_id
Expand Down Expand Up @@ -1226,10 +1227,20 @@ print_expr:
relocexpr_no_str {
printf("$%" PRIX32, $1.getConstVal());
}
| string {
| string_literal {
// Allow printing NUL characters
fwrite($1.data(), 1, $1.length(), stdout);
}
| scoped_anon_id {
if (Symbol *sym = sym_FindScopedSymbol($1); sym && sym->type == SYM_EQUS) {
std::shared_ptr<std::string> str = sym->getEqus();
fwrite(str->data(), 1, str->length(), stdout);
} else {
Expression expr;
expr.makeSymbol($1);
printf("$%" PRIX32, expr.getConstVal());
}
}
;

bit_const:
Expand All @@ -1252,10 +1263,21 @@ constlist_8bit_entry:
$1.checkNBit(8);
sect_RelByte($1, 0);
}
| string {
| string_literal {
std::vector<int32_t> output = charmap_Convert($1);
sect_ByteString(output);
}
| scoped_anon_id {
if (Symbol *sym = sym_FindScopedSymbol($1); sym && sym->type == SYM_EQUS) {
std::vector<int32_t> output = charmap_Convert(*sym->getEqus());
sect_ByteString(output);
} else {
Expression expr;
expr.makeSymbol($1);
expr.checkNBit(8);
sect_RelByte(expr, 0);
}
}
;

constlist_16bit:
Expand All @@ -1268,10 +1290,21 @@ constlist_16bit_entry:
$1.checkNBit(16);
sect_RelWord($1, 0);
}
| string {
| string_literal {
std::vector<int32_t> output = charmap_Convert($1);
sect_WordString(output);
}
| scoped_anon_id {
if (Symbol *sym = sym_FindScopedSymbol($1); sym && sym->type == SYM_EQUS) {
std::vector<int32_t> output = charmap_Convert(*sym->getEqus());
sect_WordString(output);
} else {
Expression expr;
expr.makeSymbol($1);
expr.checkNBit(16);
sect_RelWord(expr, 0);
}
}
;

constlist_32bit:
Expand All @@ -1283,10 +1316,20 @@ constlist_32bit_entry:
relocexpr_no_str {
sect_RelLong($1, 0);
}
| string {
| string_literal {
std::vector<int32_t> output = charmap_Convert($1);
sect_LongString(output);
}
| scoped_anon_id {
if (Symbol *sym = sym_FindScopedSymbol($1); sym && sym->type == SYM_EQUS) {
std::vector<int32_t> output = charmap_Convert(*sym->getEqus());
sect_LongString(output);
} else {
Expression expr;
expr.makeSymbol($1);
sect_RelLong(expr, 0);
}
}
;

reloc_8bit:
Expand Down Expand Up @@ -1318,17 +1361,17 @@ relocexpr:
relocexpr_no_str {
$$ = std::move($1);
}
| string {
| string_literal {
std::vector<int32_t> output = charmap_Convert($1);
$$.makeNumber(strToNum(output));
}
| scoped_anon_id {
$$.makeSymbol($1);
}
;

relocexpr_no_str:
scoped_anon_id {
$$.makeSymbol($1);
}
| NUMBER {
NUMBER {
$$.makeNumber($1);
}
| OP_LOGICNOT relocexpr %prec NEG {
Expand Down Expand Up @@ -1422,7 +1465,7 @@ relocexpr_no_str:
// '@' is also an ID; it is handled here
$$.makeBankSymbol($3);
}
| OP_BANK LPAREN string RPAREN {
| OP_BANK LPAREN string_literal RPAREN {
$$.makeBankSection($3);
}
| OP_SIZEOF LPAREN string RPAREN {
Expand Down Expand Up @@ -1543,7 +1586,7 @@ precision_arg:
}
;

string:
string_literal:
STRING {
$$ = std::move($1);
}
Expand Down Expand Up @@ -1606,6 +1649,19 @@ string:
}
;

string:
string_literal {
$$ = std::move($1);
}
| scoped_anon_id {
if (Symbol *sym = sym_FindScopedSymbol($1); sym && sym->type == SYM_EQUS) {
$$ = *sym->getEqus();
} else {
::error("Symbol \"%s\" is not a string symbol\n", $1.c_str());
}
}
;

strcat_args:
string {
$$ = std::move($1);
Expand All @@ -1630,10 +1686,20 @@ strfmt_va_args:
$$ = std::move($1);
$$.args.push_back(static_cast<uint32_t>($3.getConstVal()));
}
| strfmt_va_args COMMA string {
| strfmt_va_args COMMA string_literal {
$$ = std::move($1);
$$.args.push_back(std::move($3));
}
| strfmt_va_args COMMA scoped_anon_id {
$$ = std::move($1);
if (Symbol *sym = sym_FindScopedSymbol($3); sym && sym->type == SYM_EQUS) {
$$.args.push_back(*sym->getEqus());
} else {
Expression expr;
expr.makeSymbol($3);
$$.args.push_back(static_cast<uint32_t>(expr.getConstVal()));
}
}
;

section:
Expand Down

0 comments on commit 2cf28a7

Please sign in to comment.