Skip to content

Commit

Permalink
debugger: add null-terminated string output to printf/logerror
Browse files Browse the repository at this point in the history
* also added left-justification option for numeric and string formats
* removed duplication and made documentation more consistent
  • Loading branch information
pmackinlay committed Mar 20, 2024
1 parent 23c469a commit 9e3744b
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 43 deletions.
24 changes: 14 additions & 10 deletions docs/source/debugger/general.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
89 changes: 74 additions & 15 deletions src/emu/debug/debugcmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 '%':
Expand All @@ -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");
Expand All @@ -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");
Expand All @@ -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");
Expand All @@ -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");
Expand All @@ -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;
}
}

Expand Down
28 changes: 10 additions & 18 deletions src/emu/debug/debughlp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,19 +359,20 @@ 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"
"\n"
"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"
Expand All @@ -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"
Expand Down

0 comments on commit 9e3744b

Please sign in to comment.