/* * Prompt for dsh commands, then execute them, prompt again, ... * "quit", "exit", or ^D to get out. * opt (IN) program options struct */ static void _interactive_dsh(opt_t * opt) { pid_t pid; signal(SIGINT, SIG_IGN); while ((opt->cmd = _getcmd(opt->progname))) { if (*opt->cmd == '\0') { /* empty command */ Free((void **) &opt->cmd); continue; } if (*opt->cmd == '!') { /* shell escape */ _shell(opt->luid, opt->cmd + 1); Free((void **) &opt->cmd); continue; } if (strcmp(opt->cmd, "quit") == 0 /* user exit */ || strcmp(opt->cmd, "exit") == 0) { Free((void **) &opt->cmd); break; } /* must fork dsh so we can ignore SIGINT in prompt loop */ switch (pid = fork()) { case -1: errx("%p: fork: %m\n"); case 0: dsh(opt); /* run command */ exit(0); default: while (waitpid(pid, NULL, 0) < 0 && errno == EINTR); } Free((void **) &opt->cmd); } }
static void shell(void) { // Reset the cycle frequency governer to prevent spurious warnings. sim_delay_reset(); if (GDB_ATTACHED) { #ifdef DEBUG1 print_full_state(); stop_and_wait_for_gdb(); print_full_state(); return; #else return stop_and_wait_for_gdb(); #endif } print_full_state(); shell_running = true; _shell(); shell_running = false; }
static void _shell(void) { static char buf[100]; // protect <EOF> replay buf[0] = '\0'; printf("> "); if (buf != fgets(buf, 100, stdin)) { buf[0] = 'h'; buf[1] = '\0'; } switch (buf[0]) { case 'p': sscanf(buf, "%*s %x", &dumpatpc); return; #ifdef HAVE_REPLAY case 'b': sprintf(buf, "s %d", cycle - 1); // fall thru case 's': { int ret; int target; ret = sscanf(buf, "%*s %d", &target); if (-1 == ret) { target = cycle + 1; } else if (1 != ret) { WARN("Error parsing input (ret %d?)\n", ret); return _shell(); } if (target < 0) { WARN("Ignoring seek to negative cycle\n"); } else if (target == cycle) { WARN("Ignoring seek to current cycle\n"); } else { simulator_state_seek(target); print_full_state(); } return _shell(); } #endif case 'q': case 't': sim_terminate(true); case 'r': { const char *file; #if defined (HAVE_ROM) && defined (PRINT_ROM_ENABLE) if (buf[1] == 'o') { file = get_dump_name('o'); } else #endif if (buf[1] == 'a') { file = get_dump_name('a'); } else { file = NULL; buf[1] = '\0'; // now fall through 'c' to help } if (file) { char *cmd; if (-1 == asprintf(&cmd, "hexdump -C %s", file)) ERR(E_UNKNOWN, "Failure allocating cmd string\n"); FILE *out = popen(cmd, "r"); char hex_buf[100]; while ( fgets(hex_buf, 99, out) ) { printf("%s", hex_buf); } pclose(out); return _shell(); } } case '\n': sprintf(buf, "cycle %d\n", cycle+1); case 'c': if (buf[1] == 'y') { int requested_cycle; sscanf(buf, "%*s %d", &requested_cycle); if (requested_cycle < cycle) { WARN("Request to execute into the past ignored\n"); WARN("Did you mean 'seek %d'?\n", requested_cycle); return _shell(); } else if (requested_cycle == cycle) { WARN("Request to execute to current cycle ignored\n"); return _shell(); } else { dumpatcycle = requested_cycle; return; } } else if (buf[1] == 'o') { dumpatcycle = 0; dumpatpc = 0; return; } // not 'cy' or 'co', fall thru case 'h': default: printf(">> The following commands are recognized:\n"); printf(" <none> Advance 1 cycle\n"); printf(" pc HEX_ADDR Stop at pc\n"); printf(" cycle INTEGER Stop at cycle\n"); #ifdef HAVE_REPLAY printf(" seek [INTEGER] Seek to cycle\n"); #endif #if defined (HAVE_ROM) && defined (PRINT_ROM_ENABLE) printf(" rom Print ROM contents\n"); #endif #if defined (HAVE_RAM) printf(" ram Print RAM contents\n"); #endif printf(" continue Continue\n"); printf(" terminate Terminate Simulation\n"); return _shell(); } }