comparison debug.c @ 2665:54ac5fe14cf9

Allow calling functions directly as if they were commands
author Michael Pavone <pavone@retrodev.com>
date Fri, 07 Mar 2025 21:45:53 -0800
parents b0f314b19964
children 7e86ec94c899
comparison
equal deleted inserted replaced
2664:36ae207af490 2665:54ac5fe14cf9
1487 if (func->is_native) { 1487 if (func->is_native) {
1488 *out = func->impl.native(args, num_args); 1488 *out = func->impl.native(args, num_args);
1489 free(args); 1489 free(args);
1490 return 1; 1490 return 1;
1491 } else { 1491 } else {
1492 //TODO: Implement me
1493 debug_root *func_root = calloc(1, sizeof(debug_root)); 1492 debug_root *func_root = calloc(1, sizeof(debug_root));
1494 for (int i = 0; i < num_args; i++) 1493 for (int i = 0; i < num_args; i++)
1495 { 1494 {
1496 new_user_variable(func_root, func->arg_names[i], args[i]); 1495 new_user_variable(func_root, func->arg_names[i], args[i]);
1497 } 1496 }
2096 } 2095 }
2097 2096
2098 uint8_t parse_command(debug_root *root, char *text, parsed_command *out) 2097 uint8_t parse_command(debug_root *root, char *text, parsed_command *out)
2099 { 2098 {
2100 char *cur = text; 2099 char *cur = text;
2100 uint8_t is_func = 0;
2101 while (*cur && *cur != '/' && !isspace(*cur)) 2101 while (*cur && *cur != '/' && !isspace(*cur))
2102 { 2102 {
2103 if (*cur == '(') {
2104 is_func = 1;
2105 break;
2106 }
2103 ++cur; 2107 ++cur;
2104 } 2108 }
2105 char *name = malloc(cur - text + 1); 2109 char *name = malloc(cur - text + 1);
2106 memcpy(name, text, cur - text); 2110 memcpy(name, text, cur - text);
2107 name[cur-text] = 0; 2111 name[cur-text] = 0;
2108 uint8_t ret = 0; 2112 uint8_t ret = 0;
2109 tern_node *prefix_res = tern_find_prefix(root->commands, name); 2113 char *format = NULL;
2110 command_def *def = tern_find_ptr(prefix_res, ""); 2114 debug_func *func = NULL;
2111 if (!def) { 2115 command_def *def = NULL;
2112 tern_node *node = prefix_res; 2116 if (is_func) {
2113 while (node) 2117 char *start = name;
2118 for (char *ncur = name; *ncur; ncur++)
2114 { 2119 {
2115 if (node->left || node->right) { 2120 if (*ncur == ':') {
2116 break; 2121 char *nspace = malloc(ncur - start + 1);
2117 } 2122 memcpy(nspace, start, ncur - start);
2118 if (node->el) { 2123 nspace[ncur - start] = 0;
2119 node = node->straight.next; 2124 root = tern_find_ptr(root->other_roots, nspace);
2120 } else { 2125 if (!root) {
2121 def = node->straight.value.ptrval; 2126 fprintf(stderr, "%s is not a valid namespace\n", nspace);
2122 break; 2127 free(nspace);
2123 } 2128 goto cleanup_name;
2124 } 2129 }
2125 if (!def && prefix_res) { 2130 start = ncur + 1;
2126 fprintf(stderr, "%s is ambiguous. Matching commands:\n", name); 2131 }
2127 tern_foreach(prefix_res, ambiguous_iter, name); 2132 }
2133 debug_var *var = tern_find_ptr(root->variables, start);
2134 if (!var) {
2135 fprintf(stderr, "%s is not defined\n", name);
2128 goto cleanup_name; 2136 goto cleanup_name;
2129 } 2137 }
2130 } 2138 debug_val val = var->get(var);
2131 if (!def) { 2139 if (val.type != DBG_VAL_FUNC) {
2132 fprintf(stderr, "%s is not a recognized command\n", name); 2140 fprintf(stderr, "%s is not a function\n", name);
2133 goto cleanup_name; 2141 goto cleanup_name;
2134 } 2142 }
2135 char *format = NULL; 2143 func = funcs + val.v.u32;
2136 if (*cur == '/') { 2144 } else {
2137 ++cur; 2145 tern_node *prefix_res = tern_find_prefix(root->commands, name);
2138 text = cur; 2146 def = tern_find_ptr(prefix_res, "");
2139 while (*cur && !isspace(*cur)) 2147 if (!def) {
2140 { 2148 tern_node *node = prefix_res;
2149 while (node)
2150 {
2151 if (node->left || node->right) {
2152 break;
2153 }
2154 if (node->el) {
2155 node = node->straight.next;
2156 } else {
2157 def = node->straight.value.ptrval;
2158 break;
2159 }
2160 }
2161 if (!def && prefix_res) {
2162 fprintf(stderr, "%s is ambiguous. Matching commands:\n", name);
2163 tern_foreach(prefix_res, ambiguous_iter, name);
2164 goto cleanup_name;
2165 }
2166 }
2167 if (!def) {
2168 fprintf(stderr, "%s is not a recognized command\n", name);
2169 goto cleanup_name;
2170 }
2171 if (*cur == '/') {
2141 ++cur; 2172 ++cur;
2142 } 2173 text = cur;
2143 format = malloc(cur - text + 1); 2174 while (*cur && !isspace(*cur))
2144 memcpy(format, text, cur - text); 2175 {
2145 format[cur - text] = 0; 2176 ++cur;
2146 } 2177 }
2178 format = malloc(cur - text + 1);
2179 memcpy(format, text, cur - text);
2180 format[cur - text] = 0;
2181 }
2182 }
2183
2147 int num_args = 0; 2184 int num_args = 0;
2148 command_arg *args = NULL; 2185 command_arg *args = NULL;
2149 if (*cur && *cur != '\n') { 2186 if (*cur && *cur != '\n') {
2150 ++cur; 2187 ++cur;
2151 } 2188 }
2152 text = cur; 2189 text = cur;
2153 if (def->raw_args) { 2190 if (def && def->raw_args) {
2154 while (*cur && *cur != '\n') 2191 while (*cur && *cur != '\n')
2155 { 2192 {
2156 ++cur; 2193 ++cur;
2157 } 2194 }
2158 char *raw_param = NULL; 2195 char *raw_param = NULL;
2164 out->raw = raw_param; 2201 out->raw = raw_param;
2165 out->args = NULL; 2202 out->args = NULL;
2166 out->num_args = 0; 2203 out->num_args = 0;
2167 } else { 2204 } else {
2168 int arg_storage = 0; 2205 int arg_storage = 0;
2169 if (def->max_args > 0) { 2206 int32_t max_args = def ? def->max_args : func->max_args;
2170 arg_storage = def->max_args; 2207 int32_t min_args = def ? def->min_args : func->min_args;
2171 } else if (def->max_args) { 2208 if (max_args > 0) {
2172 arg_storage = def->min_args > 0 ? 2 * def->min_args : 2; 2209 arg_storage = max_args;
2210 } else if (max_args) {
2211 arg_storage = min_args > 0 ? 2 * min_args : 2;
2173 } 2212 }
2174 if (arg_storage) { 2213 if (arg_storage) {
2175 args = calloc(arg_storage, sizeof(command_arg)); 2214 args = calloc(arg_storage, sizeof(command_arg));
2176 } 2215 }
2177 while (*text && *text != '\n') 2216 while (*text && *text != '\n' && (!is_func || *text != ')'))
2178 { 2217 {
2179 char *after; 2218 char *after;
2180 expr *e = parse_expression(text, &after); 2219 expr *e = parse_expression(text, &after);
2181 if (e) { 2220 if (e) {
2182 if (num_args == arg_storage) { 2221 if (num_args == arg_storage) {
2183 if (def->max_args >= 0) { 2222 if (max_args >= 0) {
2184 free_expr(e); 2223 free_expr(e);
2185 fprintf(stderr, "Command %s takes a max of %d arguments, but at least %d provided\n", name, def->max_args, def->max_args+1); 2224 fprintf(stderr, "Command %s takes a max of %d arguments, but at least %d provided\n", name, max_args, max_args+1);
2186 goto cleanup_args; 2225 goto cleanup_args;
2187 } else { 2226 } else {
2188 arg_storage *= 2; 2227 arg_storage *= 2;
2189 args = realloc(args, arg_storage * sizeof(command_arg)); 2228 args = realloc(args, arg_storage * sizeof(command_arg));
2190 } 2229 }
2196 text = after; 2235 text = after;
2197 } else { 2236 } else {
2198 goto cleanup_args; 2237 goto cleanup_args;
2199 } 2238 }
2200 } 2239 }
2201 if (num_args < def->min_args) { 2240 if (num_args < min_args) {
2202 fprintf(stderr, "Command %s requires at least %d arguments, but only %d provided\n", name, def->min_args, num_args); 2241 fprintf(stderr, "Command %s requires at least %d arguments, but only %d provided\n", name, min_args, num_args);
2203 goto cleanup_args; 2242 goto cleanup_args;
2204 } 2243 }
2205 out->raw = NULL; 2244 out->raw = NULL;
2206 out->args = args; 2245 out->args = args;
2207 out->num_args = num_args; 2246 out->num_args = num_args;
2208 } 2247 }
2209 out->def = def; 2248 out->def = def;
2249 out->func = func ? func - funcs : 0;
2210 out->format = format; 2250 out->format = format;
2211 2251
2212 ret = 1; 2252 ret = 1;
2213 cleanup_args: 2253 cleanup_args:
2214 if (!ret) { 2254 if (!ret) {
2304 if (!strcmp(stripped, "end")) { 2344 if (!strcmp(stripped, "end")) {
2305 return END; 2345 return END;
2306 } 2346 }
2307 } 2347 }
2308 if (parse_command(root, input_buf, out)) { 2348 if (parse_command(root, input_buf, out)) {
2309 if (!out->def->has_block) { 2349 if (!out->def || !out->def->has_block) {
2310 return NORMAL; 2350 return NORMAL;
2311 } 2351 }
2312 int command_storage = 4; 2352 int command_storage = 4;
2313 command_block *block = &out->block; 2353 command_block *block = &out->block;
2314 block->commands = calloc(command_storage, sizeof(parsed_command)); 2354 block->commands = calloc(command_storage, sizeof(parsed_command));
2347 return READ_FAILED; 2387 return READ_FAILED;
2348 } 2388 }
2349 2389
2350 static uint8_t run_command(debug_root *root, parsed_command *cmd) 2390 static uint8_t run_command(debug_root *root, parsed_command *cmd)
2351 { 2391 {
2352 if (!cmd->def->raw_args && !cmd->def->skip_eval) { 2392 if (!cmd->def || (!cmd->def->raw_args && !cmd->def->skip_eval)) {
2353 for (int i = 0; i < cmd->num_args; i++) 2393 for (int i = 0; i < cmd->num_args; i++)
2354 { 2394 {
2355 if (!eval_expr(root, cmd->args[i].parsed, &cmd->args[i].value)) { 2395 if (!eval_expr(root, cmd->args[i].parsed, &cmd->args[i].value)) {
2356 fprintf(stderr, "Failed to eval %s\n", cmd->args[i].raw); 2396 fprintf(stderr, "Failed to eval %s\n", cmd->args[i].raw);
2357 return 1; 2397 return 1;
2358 } 2398 }
2359 } 2399 }
2360 } 2400 }
2361 return cmd->def->impl(root, cmd); 2401 if (cmd->def) {
2402 return cmd->def->impl(root, cmd);
2403 } else {
2404 debug_func *func = funcs + cmd->func;
2405 if (func->is_native) {
2406 debug_val *args = calloc(cmd->num_args, sizeof(debug_val));
2407 for (int i = 0; i < cmd->num_args; i++)
2408 {
2409 args[i] = cmd->args[i].value;
2410 }
2411 func->impl.native(args, cmd->num_args);
2412 free(args);
2413 } else {
2414 debug_root *func_root = calloc(1, sizeof(debug_root));
2415 for (int i = 0; i < cmd->num_args; i++)
2416 {
2417 new_user_variable(func_root, func->arg_names[i], cmd->args[i].value);
2418 }
2419 func_root->other_roots = tern_insert_ptr(func_root->other_roots, "parent", root);
2420 execute_block(func_root, &func->impl.block);
2421 //FIXME: properly free root
2422 tern_free(func_root->variables);
2423 tern_free(func_root->other_roots);
2424 free(func_root);
2425 }
2426 return 1;
2427 }
2362 } 2428 }
2363 2429
2364 static void debugger_repl(debug_root *root) 2430 static void debugger_repl(debug_root *root)
2365 { 2431 {
2366 2432