comparison debug.c @ 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
comparison
equal deleted inserted replaced
2186:935e684f2d58 2187:d0129f19ca52
1125 uint32_t addr = args[i].value; 1125 uint32_t addr = args[i].value;
1126 for (j = 0; j < sizeof(tmp)-1; j++, addr++) 1126 for (j = 0; j < sizeof(tmp)-1; j++, addr++)
1127 { 1127 {
1128 uint32_t tmp_addr = addr; 1128 uint32_t tmp_addr = addr;
1129 root->read_mem(root, &tmp_addr, 'b'); 1129 root->read_mem(root, &tmp_addr, 'b');
1130 char c = addr; 1130 char c = tmp_addr;
1131 if (c < 0x20 || c > 0x7F) { 1131 if (c < 0x20 || c > 0x7F) {
1132 break; 1132 break;
1133 } 1133 }
1134 tmp[j] = c; 1134 tmp[j] = c;
1135 } 1135 }
1136 tmp[j] = 0; 1136 tmp[j] = 0;
1137 printf(format_str, args[i].raw, tmp); 1137 printf(format_str, args[i].raw, tmp);
1138 } else { 1138 } else {
1139 printf(format_str, args[i].raw, args[i].value); 1139 printf(format_str, args[i].raw, args[i].value);
1140 }
1141 }
1142 return 1;
1143 }
1144
1145 static uint8_t cmd_printf(debug_root *root, char *format, char *param)
1146 {
1147 if (!param) {
1148 fputs("printf requires at least one parameter\n", stderr);
1149 return 1;
1150 }
1151 while (isblank(*param))
1152 {
1153 ++param;
1154 }
1155 if (*param != '"') {
1156 fprintf(stderr, "First parameter to printf must be a string, found '%s'\n", param);
1157 return 1;
1158 }
1159 ++param;
1160 char *fmt = strdup(param);
1161 char *cur = param, *out = fmt;
1162 while (*cur && *cur != '"')
1163 {
1164 if (*cur == '\\') {
1165 switch (cur[1])
1166 {
1167 case 't':
1168 *(out++) = '\t';
1169 break;
1170 case 'n':
1171 *(out++) = '\n';
1172 break;
1173 case 'r':
1174 *(out++) = '\r';
1175 break;
1176 case '\\':
1177 *(out++) = '\\';
1178 break;
1179 default:
1180 fprintf(stderr, "Unsupported escape character %c in string %s\n", cur[1], fmt);
1181 free(fmt);
1182 return 1;
1183 }
1184 cur += 2;
1185 } else {
1186 *(out++) = *(cur++);
1187 }
1188 }
1189 *out = 0;
1190 ++cur;
1191 param = cur;
1192 cur = fmt;
1193 char format_str[3] = {'%', 'd', 0};
1194 while (*cur)
1195 {
1196 if (*cur == '%') {
1197 switch(cur[1])
1198 {
1199 case 'x':
1200 case 'X':
1201 case 'c':
1202 case 'd':
1203 case 's':
1204 break;
1205 default:
1206 fprintf(stderr, "Unsupported format character %c\n", cur[1]);
1207 free(fmt);
1208 return 1;
1209 }
1210 format_str[1] = cur[1];
1211 expr *arg = parse_expression(param, &param);
1212 if (!arg) {
1213 free(fmt);
1214 return 1;
1215 }
1216 uint32_t val;
1217 if (!eval_expr(root, arg, &val)) {
1218 free(fmt);
1219 return 1;
1220 }
1221 if (cur[1] == 's') {
1222 char tmp[128];
1223 int j;
1224 for (j = 0; j < sizeof(tmp)-1; j++, val++)
1225 {
1226 uint32_t addr = val;
1227 root->read_mem(root, &addr, 'b');
1228 char c = addr;
1229 if (c < 0x20 || c > 0x7F) {
1230 break;
1231 }
1232 tmp[j] = c;
1233 }
1234 tmp[j] = 0;
1235 printf(format_str, tmp);
1236 } else {
1237 printf(format_str, val);
1238 }
1239 cur += 2;
1240 } else {
1241 putchar(*cur);
1242 ++cur;
1140 } 1243 }
1141 } 1244 }
1142 return 1; 1245 return 1;
1143 } 1246 }
1144 1247
1687 "print", NULL 1790 "print", NULL
1688 }, 1791 },
1689 .usage = "print[/FORMAT] EXPRESSION...", 1792 .usage = "print[/FORMAT] EXPRESSION...",
1690 .desc = "Print one or more expressions using the optional format character", 1793 .desc = "Print one or more expressions using the optional format character",
1691 .impl = cmd_print, 1794 .impl = cmd_print,
1795 .min_args = 1,
1796 .max_args = -1
1797 },
1798 {
1799 .names = (const char *[]){
1800 "printf", NULL
1801 },
1802 .usage = "printf FORMAT EXPRESSION...",
1803 .desc = "Print a string with C-style formatting specifiers replaced with the value of the remaining arguments",
1804 .raw_impl = cmd_printf,
1692 .min_args = 1, 1805 .min_args = 1,
1693 .max_args = -1 1806 .max_args = -1
1694 }, 1807 },
1695 { 1808 {
1696 .names = (const char *[]){ 1809 .names = (const char *[]){