changeset 2187:d0129f19ca52

Add a printf command to the debugger
author Michael Pavone <pavone@retrodev.com>
date Sun, 14 Aug 2022 17:37:37 -0700
parents 935e684f2d58
children e17d99c96c89
files debug.c
diffstat 1 files changed, 114 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/debug.c	Sun Aug 14 09:55:06 2022 -0700
+++ b/debug.c	Sun Aug 14 17:37:37 2022 -0700
@@ -1127,7 +1127,7 @@
 			{
 				uint32_t tmp_addr = addr;
 				root->read_mem(root, &tmp_addr, 'b');
-				char c = addr;
+				char c = tmp_addr;
 				if (c < 0x20 || c > 0x7F) {
 					break;
 				}
@@ -1142,6 +1142,109 @@
 	return 1;
 }
 
+static uint8_t cmd_printf(debug_root *root, char *format, char *param)
+{
+	if (!param) {
+		fputs("printf requires at least one parameter\n", stderr);
+		return 1;
+	}
+	while (isblank(*param))
+	{
+		++param;
+	}
+	if (*param != '"') {
+		fprintf(stderr, "First parameter to printf must be a string, found '%s'\n", param);
+		return 1;
+	}
+	++param;
+	char *fmt = strdup(param);
+	char *cur = param, *out = fmt;
+	while (*cur && *cur != '"')
+	{
+		if (*cur == '\\') {
+			switch (cur[1])
+			{
+			case 't':
+				*(out++) = '\t';
+				break;
+			case 'n':
+				*(out++) = '\n';
+				break;
+			case 'r':
+				*(out++) = '\r';
+				break;
+			case '\\':
+				*(out++) = '\\';
+				break;
+			default:
+				fprintf(stderr, "Unsupported escape character %c in string %s\n", cur[1], fmt);
+				free(fmt);
+				return 1;
+			}
+			cur += 2;
+		} else {
+			*(out++) = *(cur++);
+		}
+	}
+	*out = 0;
+	++cur;
+	param = cur;
+	cur = fmt;
+	char format_str[3] = {'%', 'd', 0};
+	while (*cur)
+	{
+		if (*cur == '%') {
+			switch(cur[1])
+			{
+			case 'x':
+			case 'X':
+			case 'c':
+			case 'd':
+			case 's':
+				break;
+			default:
+				fprintf(stderr, "Unsupported format character %c\n", cur[1]);
+				free(fmt);
+				return 1;
+			}
+			format_str[1] = cur[1];
+			expr *arg = parse_expression(param, &param);
+			if (!arg) {
+				free(fmt);
+				return 1;
+			}
+			uint32_t val;
+			if (!eval_expr(root, arg, &val)) {
+				free(fmt);
+				return 1;
+			}
+			if (cur[1] == 's') {
+				char tmp[128];
+				int j;
+				for (j = 0; j < sizeof(tmp)-1; j++, val++)
+				{
+					uint32_t addr = val;
+					root->read_mem(root, &addr, 'b');
+					char c = addr;
+					if (c < 0x20 || c > 0x7F) {
+						break;
+					}
+					tmp[j] = c;
+				}
+				tmp[j] = 0;
+				printf(format_str, tmp);
+			} else {
+				printf(format_str, val);
+			}
+			cur += 2;
+		} else {
+			putchar(*cur);
+			++cur;
+		}
+	}
+	return 1;
+}
+
 static uint8_t cmd_display(debug_root *root, char *format, int num_args, command_arg *args)
 {
 	cmd_print(root, format, num_args, args);
@@ -1694,6 +1797,16 @@
 	},
 	{
 		.names = (const char *[]){
+			"printf", NULL
+		},
+		.usage = "printf FORMAT EXPRESSION...",
+		.desc = "Print a string with C-style formatting specifiers replaced with the value of the remaining arguments",
+		.raw_impl = cmd_printf,
+		.min_args = 1,
+		.max_args = -1
+	},
+	{
+		.names = (const char *[]){
 			"softreset", "sr", NULL
 		},
 		.usage = "softreset",