summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Patrick Mackinlay <pmackinlay@hotmail.com>2024-03-20 23:12:11 +0700
committer GitHub <noreply@github.com>2024-03-21 03:12:11 +1100
commitf93a04010a06aa7f6793b7c0d28d31aaba9520fa (patch)
tree0bbdff4b9fe9e77dbc768d90a53cbf4a0479188b
parent80e9125a5bb126aaf2b3d88ac91b09f4ca2676f6 (diff)
emu/debug/debugcmd.cpp: Add NUL-terminated string argument support to printf/logerror. (#12124)
* Use %s to read NUL-terminated strings from emulated memory. Precision sets maximum length. * Also added left-justification option for numeric and string formats. * Made documentation more consistent and removed duplication.
-rw-r--r--docs/source/debugger/general.rst24
-rw-r--r--src/emu/debug/debugcmd.cpp89
-rw-r--r--src/emu/debug/debughlp.cpp28
3 files changed, 98 insertions, 43 deletions
diff --git a/docs/source/debugger/general.rst b/docs/source/debugger/general.rst
index 13060894aae..c01ef20dea8 100644
--- a/docs/source/debugger/general.rst
+++ b/docs/source/debugger/general.rst
@@ -190,18 +190,22 @@ available:
%c
Prints the corresponding argument as an 8-bit character.
-%[0][<n>]d
+%[-][0][<n>]d
Prints the corresponding argument as a decimal number with optional
- minimum field width and zero fill.
-%[0][<n>]o
+ left justification, zero fill and minimum field width.
+%[-][0][<n>]o
Prints the corresponding argument as an octal number with optional
- minimum field width and zero fill using lowercase letters.
-%[0][<n>]x
- Prints the corresponding argument as a hexadecimal number with
- optional minimum field width and zero fill using lowercase letters.
-%[0][<n>]X
- Prints the corresponding argument as a hexadecimal number with
- optional minimum field width and zero fill using uppercase letters.
+ left justification, zero fill and minimum field width.
+%[-][0][<n>]x
+ Prints the corresponding argument as a lowercase hexadecimal number
+ with optional left justification, zero fill and minimum field width.
+%[-][0][<n>]X
+ Prints the corresponding argument as an uppercase hexadecimal number
+ with optional left justification, zero fill and minimum field width.
+%[-][<n>][.[<n>]]s
+ Prints a null-terminated string of 8-bit characters from the address
+ and address space given by the corresponding argument, with optional
+ left justification, minimum and maximum field widths.
\%%
Prints a literal percent symbol.
\\n
diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp
index 082324a6d94..ad463ace500 100644
--- a/src/emu/debug/debugcmd.cpp
+++ b/src/emu/debug/debugcmd.cpp
@@ -471,7 +471,7 @@ void debugger_commands::execute_print(const std::vector<std::string_view> &param
bool debugger_commands::mini_printf(std::ostream &stream, const std::vector<std::string_view> &params)
{
- std::string_view format(params[0]);
+ std::string_view const format(params[0]);
auto f = format.begin();
int param = 1;
@@ -499,21 +499,48 @@ bool debugger_commands::mini_printf(std::ostream &stream, const std::vector<std:
// formatting
else if (c == '%')
{
+ bool left_justify = false;
+ bool zero_fill = false;
int width = 0;
- int zerofill = 0;
+ int precision = 0;
- // parse out the width
- while (f != format.end() && *f >= '0' && *f <= '9')
+ // parse optional left justification flag
+ if (f != format.end() && *f == '-')
{
- c = *f++;
- if (c == '0' && width == 0)
- zerofill = 1;
- width = width * 10 + (c - '0');
+ left_justify = true;
+ f++;
+ }
+
+ // parse optional zero fill flag
+ if (f != format.end() && *f == '0')
+ {
+ zero_fill = true;
+ f++;
+ }
+
+ // parse optional width
+ while (f != format.end() && isdigit(*f))
+ width = width * 10 + (*f++ - '0');
+ if (f == format.end())
+ break;
+
+ // apply left justification
+ if (left_justify)
+ width = -width;
+
+ if ((c = *f++) == '.')
+ {
+ // parse optional precision
+ while (f != format.end() && isdigit(*f))
+ precision = precision * 10 + (*f++ - '0');
+
+ // get the format
+ if (f != format.end())
+ c = *f++;
+ else
+ break;
}
- if (f == format.end()) break;
- // get the format
- c = *f++;
switch (c)
{
case '%':
@@ -522,7 +549,7 @@ bool debugger_commands::mini_printf(std::ostream &stream, const std::vector<std:
case 'X':
if (param < params.size() && m_console.validate_number_parameter(params[param++], number))
- util::stream_format(stream, zerofill ? "%0*X" : "%*X", width, number);
+ util::stream_format(stream, zero_fill ? "%0*X" : "%*X", width, number);
else
{
m_console.printf("Not enough parameters for format!\n");
@@ -531,7 +558,7 @@ bool debugger_commands::mini_printf(std::ostream &stream, const std::vector<std:
break;
case 'x':
if (param < params.size() && m_console.validate_number_parameter(params[param++], number))
- util::stream_format(stream, zerofill ? "%0*x" : "%*x", width, number);
+ util::stream_format(stream, zero_fill ? "%0*x" : "%*x", width, number);
else
{
m_console.printf("Not enough parameters for format!\n");
@@ -542,7 +569,7 @@ bool debugger_commands::mini_printf(std::ostream &stream, const std::vector<std:
case 'O':
case 'o':
if (param < params.size() && m_console.validate_number_parameter(params[param++], number))
- util::stream_format(stream, zerofill ? "%0*o" : "%*o", width, number);
+ util::stream_format(stream, zero_fill ? "%0*o" : "%*o", width, number);
else
{
m_console.printf("Not enough parameters for format!\n");
@@ -553,7 +580,7 @@ bool debugger_commands::mini_printf(std::ostream &stream, const std::vector<std:
case 'D':
case 'd':
if (param < params.size() && m_console.validate_number_parameter(params[param++], number))
- util::stream_format(stream, zerofill ? "%0*d" : "%*d", width, number);
+ util::stream_format(stream, zero_fill ? "%0*d" : "%*d", width, number);
else
{
m_console.printf("Not enough parameters for format!\n");
@@ -572,6 +599,38 @@ bool debugger_commands::mini_printf(std::ostream &stream, const std::vector<std:
}
break;
+ case 's':
+ {
+ address_space *space;
+ if (param < params.size() && m_console.validate_target_address_parameter(params[param++], -1, space, number))
+ {
+ address_space *tspace;
+ std::string s;
+
+ for (u32 address = u32(number), taddress; space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, taddress = address, tspace); address++)
+ {
+ u8 const data = tspace->read_byte(taddress);
+
+ if (!data)
+ break;
+
+ s += data;
+
+ if (precision == 1)
+ break;
+ else if (precision)
+ precision--;
+ }
+
+ util::stream_format(stream, "%*s", width, s);
+ }
+ else
+ {
+ m_console.printf("Not enough parameters for format!\n");
+ return false;
+ }
+ }
+ break;
}
}
diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp
index 5d71d81e0ba..76102402bcb 100644
--- a/src/emu/debug/debughlp.cpp
+++ b/src/emu/debug/debughlp.cpp
@@ -359,11 +359,12 @@ const help_item f_static_help_list[] =
"The printf command performs a C-style printf to the debugger console. Only a very limited set of "
"formatting options are available:\n"
"\n"
- " %c -- 8-bit character\n"
- " %[0][<n>]d -- decimal number with optional digit count and zero-fill\n"
- " %[0][<n>]o -- octal number with optional digit count and zero-fill\n"
- " %[0][<n>]x -- hexadecimal number with optional digit count and zero-fill (lowercase digits)\n"
- " %[0][<n>]X -- hexadecimal number with optional digit count and zero-fill (uppercase digits)\n"
+ " %c -- 8-bit character\n"
+ " %[-][0][<n>]d -- decimal number with optional left justification, zero fill and minimum width\n"
+ " %[-][0][<n>]o -- octal number with optional left justification, zero fill and minimum width\n"
+ " %[-][0][<n>]x -- lowercase hexadecimal number with optional left justification, zero fill and minimum width\n"
+ " %[-][0][<n>]X -- uppercase hexadecimal number with optional left justification, zero fill and minimum width\n"
+ " %[-][<n>][.[<n>]]s -- null-terminated string of 8-bit characters with optional left justification, minimum and maximum width\n"
"\n"
"All remaining formatting options are ignored. Use %% to output a % character. Multiple lines can be "
"printed by embedding a \\n in the text.\n"
@@ -371,7 +372,7 @@ const help_item f_static_help_list[] =
"Examples:\n"
"\n"
"printf \"PC=%04X\",pc\n"
- " Prints PC=<pcval> where <pcval> is displayed in hexadecimal with 4 digits with zero-fill.\n"
+ " Prints PC=<pcval> where <pcval> is displayed in uppercase hexadecimal with 4 digits and zero fill.\n"
"\n"
"printf \"A=%d, B=%d\\nC=%d\",a,b,a+b\n"
" Prints A=<aval>, B=<bval> on one line, and C=<a+bval> on a second line.\n"
@@ -382,21 +383,12 @@ const help_item f_static_help_list[] =
" logerror <format>[,<item>[,...]]\n"
"\n"
"The logerror command performs a C-style printf to the error log. Only a very limited set of "
- "formatting options are available:\n"
- "\n"
- " %c -- 8-bit character\n"
- " %[0][<n>]d -- decimal number with optional digit count and zero-fill\n"
- " %[0][<n>]o -- octal number with optional digit count and zero-fill\n"
- " %[0][<n>]x -- hexadecimal number with optional digit count and zero-fill (lowercase digits)\n"
- " %[0][<n>]X -- hexadecimal number with optional digit count and zero-fill (uppercase digits)\n"
- "\n"
- "All remaining formatting options are ignored. Use %% to output a % character. Multiple lines can be "
- "printed by embedding a \\n in the text.\n"
+ "formatting options are available. See the 'printf' help for details.\n"
"\n"
"Examples:\n"
"\n"
- "logerror \"PC=%04X\",pc\n"
- " Logs PC=<pcval> where <pcval> is displayed in hexadecimal with 4 digits with zero-fill.\n"
+ "logerror \"PC=%04x\",pc\n"
+ " Logs PC=<pcval> where <pcval> is displayed in lowercase hexadecimal with 4 digits and zero fill.\n"
"\n"
"logerror \"A=%d, B=%d\\nC=%d\",a,b,a+b\n"
" Logs A=<aval>, B=<bval> on one line, and C=<a+bval> on a second line.\n"