Merge pull request #390 from ISSOtm/print_types

Add "print types" to bracketed symbols
This commit is contained in:
Eldred Habert
2019-08-29 20:12:32 +02:00
committed by GitHub
7 changed files with 114 additions and 8 deletions

View File

@@ -39,6 +39,7 @@ extern struct sSymbol *tHashedSymbols[HASHSIZE];
extern struct sSymbol *pPCSymbol;
extern bool oDontExpandStrings;
size_t symvaluetostring(char *dest, size_t maxLength, char *sym);
size_t symvaluetostring(char *dest, size_t maxLength, char *sym,
const char *mode);
#endif /* RGBDS_ASM_ASM_H */

View File

@@ -1,7 +1,7 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
@@ -75,7 +75,8 @@ static void bankrangecheck(char *name, uint32_t secttype, int32_t org,
out_NewAbsSection(name, secttype, org, bank);
}
size_t symvaluetostring(char *dest, size_t maxLength, char *sym)
size_t symvaluetostring(char *dest, size_t maxLength, char *sym,
const char *mode)
{
size_t length;
@@ -83,6 +84,9 @@ size_t symvaluetostring(char *dest, size_t maxLength, char *sym)
char *src = sym_GetStringValue(sym);
size_t i;
if (mode)
yyerror("Print types are only allowed for numbers");
for (i = 0; src[i] != 0; i++) {
if (i >= maxLength)
fatalerror("Symbol value too long to fit buffer");
@@ -94,8 +98,25 @@ size_t symvaluetostring(char *dest, size_t maxLength, char *sym)
} else {
uint32_t value = sym_GetConstantValue(sym);
int32_t fullLength = snprintf(dest, maxLength + 1, "$%X",
int32_t fullLength;
/* Special cheat for binary */
if (mode && !mode[0]) {
char binary[33]; /* 32 bits + 1 terminator */
char *write_ptr = binary + 32;
fullLength = 0;
binary[32] = 0;
do {
*(--write_ptr) = (value & 1) + '0';
value >>= 1;
fullLength++;
} while(value);
strncpy(dest, write_ptr, maxLength + 1);
} else {
fullLength = snprintf(dest, maxLength + 1,
mode ? : "$%X",
value);
}
if (fullLength < 0) {
fatalerror("snprintf encoding error");

View File

@@ -1,7 +1,7 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
@@ -599,6 +599,7 @@ size_t yylex_ReadBracketedSymbol(char *dest, size_t index)
char ch;
size_t i = 0;
size_t length, maxLength;
const char *mode = NULL;
for (ch = *pLexBuffer;
ch != '}' && ch != '"' && ch != '\n';
@@ -612,16 +613,42 @@ size_t yylex_ReadBracketedSymbol(char *dest, size_t index)
i += length;
else
fatalerror("Illegal character escape '%c'", ch);
} else if (ch == ':' && !mode) { /* Only grab 1st colon */
/* Use a whitelist of modes, which does prevent the
* use of some features such as precision,
* but also avoids a security flaw
*/
const char *acceptedModes = "bxXd";
/* Binary isn't natively supported,
* so it's handled differently
*/
static const char * const formatSpecifiers[] = {
"", "%x", "%X", "%d"
};
/* Prevent reading out of bounds! */
const char *designatedMode;
if (i != 1)
fatalerror("Print types are exactly 1 character long");
designatedMode = strchr(acceptedModes, sym[i - 1]);
if (!designatedMode)
fatalerror("Illegal print type '%c'",
sym[i - 1]);
mode = formatSpecifiers[designatedMode - acceptedModes];
/* Begin writing the symbol again */
i = 0;
} else {
yylex_SymbolWriteChar(sym, i++, ch);
}
}
/* Properly terminate the string */
yylex_SymbolWriteChar(sym, i, 0);
/* It's assumed we're writing to a T_STRING */
maxLength = MAXSTRLEN - index;
length = symvaluetostring(&dest[index], maxLength, sym);
length = symvaluetostring(&dest[index], maxLength, sym, mode);
if (*pLexBuffer == '}')
pLexBuffer++;

View File

@@ -1079,7 +1079,20 @@ within a string.
This will examine the type of the symbol and insert its value accordingly.
If symbol is a string symbol, the symbols value is simply copied.
If it's a numeric symbol, the value is converted to hexadecimal notation and
inserted as a string.
inserted as a string with a dollar prepended.
.Pp
It's possible to change the way numeric symbols are converted by specifying
a print type like so:
.Sy {d:symbol}
Valid print types are:
.Bl -column -offset indent
.It Sy Print type Ta Sy Format Ta Sy Example
.It Li d Ta Decimal Ta 42
.It Li x Ta Lowercase hexadecimal Ta 2a
.It Li X Ta Uppercase hexadecimal Ta 2A
.It Li b Ta Binary Ta 101010
.Pp
Note that print types should only be used with numeric values, not strings.
.Pp
HINT: The
.Sy {symbol}

View File

@@ -0,0 +1,20 @@
X = 42
PRINTT "{X}\n"
PRINTT "{x:X}\n"
PRINTT "{X:X}\n"
PRINTT "{d:X}\n"
PRINTT "{b:X}\n"
Y equ 1337
PRINTT "{b:Y}\n"
rsreset
R rb 0
PRINTT "{d:R}\n"
S equs "You can't format me!"
PRINTT "{X:S}\n"
SECTION "Test", ROM0
Label:
PRINTT "{x:Label}\n"

View File

@@ -0,0 +1,12 @@
ERROR: bracketed-symbols.asm(16):
Print types are only allowed for numbers
ERROR: bracketed-symbols.asm(20):
Expression must have a constant value
$2A
2a
2A
42
101010
10100111001
0
You can't format me!

View File

@@ -0,0 +1,12 @@
ERROR: -(16):
Print types are only allowed for numbers
ERROR: -(20):
Expression must have a constant value
$2A
2a
2A
42
101010
10100111001
0
You can't format me!