Implement multi-value charmaps (#1429)

This commit is contained in:
Sylvie
2024-08-04 17:32:08 -04:00
committed by GitHub
parent 436580a649
commit 9a5b3f0902
16 changed files with 181 additions and 89 deletions

View File

@@ -70,7 +70,7 @@
yy::parser::symbol_type yylex(); // Provided by lexer.cpp
static uint32_t str2int2(std::vector<uint8_t> const &s);
static uint32_t str2int2(std::vector<int32_t> const &s);
static void errorInvalidUTF8Byte(uint8_t byte, char const *functionName);
static size_t strlenUTF8(std::string const &str);
static std::string strsubUTF8(std::string const &str, uint32_t pos, uint32_t len);
@@ -105,7 +105,6 @@
%type <Expression> relocexpr_no_str
%type <int32_t> const
%type <int32_t> const_no_str
%type <int32_t> const_8bit
%type <int32_t> uconst
%type <int32_t> rs_uconst
%type <int32_t> shift_const
@@ -264,6 +263,7 @@
%type <std::vector<Expression>> ds_args
%type <std::vector<std::string>> purge_args
%type <std::vector<int32_t>> charmap_args
%type <ForArgs> for_args
%token Z80_ADC "adc" Z80_ADD "add" Z80_AND "and"
@@ -1083,8 +1083,18 @@ incbin:
;
charmap:
POP_CHARMAP string COMMA const_8bit {
charmap_Add($2, (uint8_t)$4);
POP_CHARMAP string COMMA charmap_args trailing_comma {
charmap_Add($2, std::move($4));
}
;
charmap_args:
const {
$$.push_back(std::move($1));
}
| charmap_args COMMA const {
$$ = std::move($1);
$$.push_back(std::move($3));
}
;
@@ -1170,7 +1180,7 @@ constlist_8bit_entry:
sect_RelByte($1, 0);
}
| string {
std::vector<uint8_t> output = charmap_Convert($1);
std::vector<int32_t> output = charmap_Convert($1);
sect_AbsByteString(output);
}
;
@@ -1185,7 +1195,7 @@ constlist_16bit_entry:
sect_RelWord($1, 0);
}
| string {
std::vector<uint8_t> output = charmap_Convert($1);
std::vector<int32_t> output = charmap_Convert($1);
sect_AbsWordString(output);
}
;
@@ -1200,7 +1210,7 @@ constlist_32bit_entry:
sect_RelLong($1, 0);
}
| string {
std::vector<uint8_t> output = charmap_Convert($1);
std::vector<int32_t> output = charmap_Convert($1);
sect_AbsLongString(output);
}
;
@@ -1250,7 +1260,7 @@ relocexpr:
$$ = std::move($1);
}
| string {
std::vector<uint8_t> output = charmap_Convert($1);
std::vector<int32_t> output = charmap_Convert($1);
$$.makeNumber(str2int2(output));
}
;
@@ -1465,12 +1475,6 @@ const_no_str:
}
;
const_8bit:
reloc_8bit {
$$ = $1.getConstVal();
}
;
opt_q_arg:
%empty {
$$ = fix_Precision();
@@ -2374,26 +2378,37 @@ void yy::parser::error(std::string const &str) {
::error("%s\n", str.c_str());
}
static uint32_t str2int2(std::vector<uint8_t> const &s) {
static uint32_t str2int2(std::vector<int32_t> const &s) {
uint32_t length = s.size();
if (length == 1) {
// The string is a single character with a single value,
// which can be used directly as a number.
return (uint32_t)s[0];
}
for (int32_t v : s) {
if (!checkNBit(v, 8, "All character units"))
break;
}
if (length > 4)
warning(
WARNING_NUMERIC_STRING_1,
"Treating string as a number ignores first %" PRIu32 " character%s\n",
"Treating string as a number ignores first %" PRIu32 " byte%s\n",
length - 4,
length == 5 ? "" : "s"
);
else if (length > 1)
warning(
WARNING_NUMERIC_STRING_2, "Treating %" PRIu32 "-character string as a number\n", length
WARNING_NUMERIC_STRING_2, "Treating %" PRIu32 "-byte string as a number\n", length
);
uint32_t r = 0;
for (uint32_t i = length < 4 ? 0 : length - 4; i < length; i++) {
r <<= 8;
r |= s[i];
r |= static_cast<uint8_t>(s[i]);
}
return r;