Skip to content

Commit f93a040

Browse files
authored
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.
1 parent 80e9125 commit f93a040

File tree

3 files changed

+98
-43
lines changed

3 files changed

+98
-43
lines changed

Diff for: docs/source/debugger/general.rst

+14-10
Original file line numberDiff line numberDiff line change
@@ -190,18 +190,22 @@ available:
190190

191191
%c
192192
Prints the corresponding argument as an 8-bit character.
193-
%[0][<n>]d
193+
%[-][0][<n>]d
194194
Prints the corresponding argument as a decimal number with optional
195-
minimum field width and zero fill.
196-
%[0][<n>]o
195+
left justification, zero fill and minimum field width.
196+
%[-][0][<n>]o
197197
Prints the corresponding argument as an octal number with optional
198-
minimum field width and zero fill using lowercase letters.
199-
%[0][<n>]x
200-
Prints the corresponding argument as a hexadecimal number with
201-
optional minimum field width and zero fill using lowercase letters.
202-
%[0][<n>]X
203-
Prints the corresponding argument as a hexadecimal number with
204-
optional minimum field width and zero fill using uppercase letters.
198+
left justification, zero fill and minimum field width.
199+
%[-][0][<n>]x
200+
Prints the corresponding argument as a lowercase hexadecimal number
201+
with optional left justification, zero fill and minimum field width.
202+
%[-][0][<n>]X
203+
Prints the corresponding argument as an uppercase hexadecimal number
204+
with optional left justification, zero fill and minimum field width.
205+
%[-][<n>][.[<n>]]s
206+
Prints a null-terminated string of 8-bit characters from the address
207+
and address space given by the corresponding argument, with optional
208+
left justification, minimum and maximum field widths.
205209
\%%
206210
Prints a literal percent symbol.
207211
\\n

Diff for: src/emu/debug/debugcmd.cpp

+74-15
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ void debugger_commands::execute_print(const std::vector<std::string_view> &param
471471

472472
bool debugger_commands::mini_printf(std::ostream &stream, const std::vector<std::string_view> &params)
473473
{
474-
std::string_view format(params[0]);
474+
std::string_view const format(params[0]);
475475
auto f = format.begin();
476476

477477
int param = 1;
@@ -499,21 +499,48 @@ bool debugger_commands::mini_printf(std::ostream &stream, const std::vector<std:
499499
// formatting
500500
else if (c == '%')
501501
{
502+
bool left_justify = false;
503+
bool zero_fill = false;
502504
int width = 0;
503-
int zerofill = 0;
505+
int precision = 0;
504506

505-
// parse out the width
506-
while (f != format.end() && *f >= '0' && *f <= '9')
507+
// parse optional left justification flag
508+
if (f != format.end() && *f == '-')
507509
{
508-
c = *f++;
509-
if (c == '0' && width == 0)
510-
zerofill = 1;
511-
width = width * 10 + (c - '0');
510+
left_justify = true;
511+
f++;
512+
}
513+
514+
// parse optional zero fill flag
515+
if (f != format.end() && *f == '0')
516+
{
517+
zero_fill = true;
518+
f++;
519+
}
520+
521+
// parse optional width
522+
while (f != format.end() && isdigit(*f))
523+
width = width * 10 + (*f++ - '0');
524+
if (f == format.end())
525+
break;
526+
527+
// apply left justification
528+
if (left_justify)
529+
width = -width;
530+
531+
if ((c = *f++) == '.')
532+
{
533+
// parse optional precision
534+
while (f != format.end() && isdigit(*f))
535+
precision = precision * 10 + (*f++ - '0');
536+
537+
// get the format
538+
if (f != format.end())
539+
c = *f++;
540+
else
541+
break;
512542
}
513-
if (f == format.end()) break;
514543

515-
// get the format
516-
c = *f++;
517544
switch (c)
518545
{
519546
case '%':
@@ -522,7 +549,7 @@ bool debugger_commands::mini_printf(std::ostream &stream, const std::vector<std:
522549

523550
case 'X':
524551
if (param < params.size() && m_console.validate_number_parameter(params[param++], number))
525-
util::stream_format(stream, zerofill ? "%0*X" : "%*X", width, number);
552+
util::stream_format(stream, zero_fill ? "%0*X" : "%*X", width, number);
526553
else
527554
{
528555
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:
531558
break;
532559
case 'x':
533560
if (param < params.size() && m_console.validate_number_parameter(params[param++], number))
534-
util::stream_format(stream, zerofill ? "%0*x" : "%*x", width, number);
561+
util::stream_format(stream, zero_fill ? "%0*x" : "%*x", width, number);
535562
else
536563
{
537564
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:
542569
case 'O':
543570
case 'o':
544571
if (param < params.size() && m_console.validate_number_parameter(params[param++], number))
545-
util::stream_format(stream, zerofill ? "%0*o" : "%*o", width, number);
572+
util::stream_format(stream, zero_fill ? "%0*o" : "%*o", width, number);
546573
else
547574
{
548575
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:
553580
case 'D':
554581
case 'd':
555582
if (param < params.size() && m_console.validate_number_parameter(params[param++], number))
556-
util::stream_format(stream, zerofill ? "%0*d" : "%*d", width, number);
583+
util::stream_format(stream, zero_fill ? "%0*d" : "%*d", width, number);
557584
else
558585
{
559586
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:
572599
}
573600
break;
574601

602+
case 's':
603+
{
604+
address_space *space;
605+
if (param < params.size() && m_console.validate_target_address_parameter(params[param++], -1, space, number))
606+
{
607+
address_space *tspace;
608+
std::string s;
609+
610+
for (u32 address = u32(number), taddress; space->device().memory().translate(space->spacenum(), device_memory_interface::TR_READ, taddress = address, tspace); address++)
611+
{
612+
u8 const data = tspace->read_byte(taddress);
613+
614+
if (!data)
615+
break;
616+
617+
s += data;
618+
619+
if (precision == 1)
620+
break;
621+
else if (precision)
622+
precision--;
623+
}
624+
625+
util::stream_format(stream, "%*s", width, s);
626+
}
627+
else
628+
{
629+
m_console.printf("Not enough parameters for format!\n");
630+
return false;
631+
}
632+
}
633+
break;
575634
}
576635
}
577636

Diff for: src/emu/debug/debughlp.cpp

+10-18
Original file line numberDiff line numberDiff line change
@@ -359,19 +359,20 @@ const help_item f_static_help_list[] =
359359
"The printf command performs a C-style printf to the debugger console. Only a very limited set of "
360360
"formatting options are available:\n"
361361
"\n"
362-
" %c -- 8-bit character\n"
363-
" %[0][<n>]d -- decimal number with optional digit count and zero-fill\n"
364-
" %[0][<n>]o -- octal number with optional digit count and zero-fill\n"
365-
" %[0][<n>]x -- hexadecimal number with optional digit count and zero-fill (lowercase digits)\n"
366-
" %[0][<n>]X -- hexadecimal number with optional digit count and zero-fill (uppercase digits)\n"
362+
" %c -- 8-bit character\n"
363+
" %[-][0][<n>]d -- decimal number with optional left justification, zero fill and minimum width\n"
364+
" %[-][0][<n>]o -- octal number with optional left justification, zero fill and minimum width\n"
365+
" %[-][0][<n>]x -- lowercase hexadecimal number with optional left justification, zero fill and minimum width\n"
366+
" %[-][0][<n>]X -- uppercase hexadecimal number with optional left justification, zero fill and minimum width\n"
367+
" %[-][<n>][.[<n>]]s -- null-terminated string of 8-bit characters with optional left justification, minimum and maximum width\n"
367368
"\n"
368369
"All remaining formatting options are ignored. Use %% to output a % character. Multiple lines can be "
369370
"printed by embedding a \\n in the text.\n"
370371
"\n"
371372
"Examples:\n"
372373
"\n"
373374
"printf \"PC=%04X\",pc\n"
374-
" Prints PC=<pcval> where <pcval> is displayed in hexadecimal with 4 digits with zero-fill.\n"
375+
" Prints PC=<pcval> where <pcval> is displayed in uppercase hexadecimal with 4 digits and zero fill.\n"
375376
"\n"
376377
"printf \"A=%d, B=%d\\nC=%d\",a,b,a+b\n"
377378
" 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[] =
382383
" logerror <format>[,<item>[,...]]\n"
383384
"\n"
384385
"The logerror command performs a C-style printf to the error log. Only a very limited set of "
385-
"formatting options are available:\n"
386-
"\n"
387-
" %c -- 8-bit character\n"
388-
" %[0][<n>]d -- decimal number with optional digit count and zero-fill\n"
389-
" %[0][<n>]o -- octal number with optional digit count and zero-fill\n"
390-
" %[0][<n>]x -- hexadecimal number with optional digit count and zero-fill (lowercase digits)\n"
391-
" %[0][<n>]X -- hexadecimal number with optional digit count and zero-fill (uppercase digits)\n"
392-
"\n"
393-
"All remaining formatting options are ignored. Use %% to output a % character. Multiple lines can be "
394-
"printed by embedding a \\n in the text.\n"
386+
"formatting options are available. See the 'printf' help for details.\n"
395387
"\n"
396388
"Examples:\n"
397389
"\n"
398-
"logerror \"PC=%04X\",pc\n"
399-
" Logs PC=<pcval> where <pcval> is displayed in hexadecimal with 4 digits with zero-fill.\n"
390+
"logerror \"PC=%04x\",pc\n"
391+
" Logs PC=<pcval> where <pcval> is displayed in lowercase hexadecimal with 4 digits and zero fill.\n"
400392
"\n"
401393
"logerror \"A=%d, B=%d\\nC=%d\",a,b,a+b\n"
402394
" Logs A=<aval>, B=<bval> on one line, and C=<a+bval> on a second line.\n"

0 commit comments

Comments
 (0)