/* debug.h - Debugging implementation. Copyright (C) 2007 Free Software Foundation, Inc. Written by Neal H. Walfield . This file is part of the GNU Hurd. The GNU Hurd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. The GNU Hurd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "debug.h" #include "shutdown.h" #include "scheduler.h" #include "thread.h" #include "object.h" #include "activity.h" #include int output_debug; static struct debug_command reboot_command = { "reboot", '6', "Reboot the machine.", (void (*) (int, const char *[])) reset, NULL }; static struct debug_command halt_command = { "halt", '^', "Halt the machine.", (void (*) (int, const char *[])) halt, &reboot_command }; static int continue_execution; static void do_continue_execution (int argc, char *argv[]) { continue_execution = 1; } static struct debug_command continue_command = { "continue", 'c', "Continue execution.", (void (*) (int, const char *[])) do_continue_execution, &halt_command }; static void help (int argc, char *argv[]); static struct debug_command help_command = { "help", '?', NULL, (void (*) (int, const char *[])) help, &continue_command }; static struct debug_command *commands = &help_command; static void help (int argc, char *argv[]) { struct debug_command *cmd; int maxlen = 0; for (cmd = commands; cmd; cmd = cmd->next) if (cmd->help && maxlen < strlen (cmd->name)) maxlen = strlen (cmd->name); for (cmd = commands; cmd; cmd = cmd->next) if (cmd->help) { printf ("%s", cmd->name); int i; for (i = strlen (cmd->name); i < maxlen; i ++) putchar (' '); printf (" %c %s\n", cmd->short_name ?: ' ', cmd->help); } } void debug_register (struct debug_command *command) { command->next = commands; commands = command; } void debugger (void) { continue_execution = 0; while (! continue_execution) { #define BUFFER_SIZE (sizeof (buffer)) char buffer[128]; int len = 0; printf ("\ndebugger> "); /* Read a line of input. */ while (len == 0 || buffer[len - 1] != 0) { int c = getchar (); switch (c) { case 27: /* Escape. */ return; case 127: /* Delete. */ c = 8; /* Fall through. */ case 8: /* Backspace. */ if (len > 0) { len --; printf ("%c ", 8); } else continue; break; case '\n': case '\r': buffer[len ++] = 0; printf ("\n"); break; default: buffer[len ++] = c; break; } printf ("%c", c); } buffer[len - 1] = '\0'; #define ARGS 10 char *argv[ARGS]; int argc = 0; char *p = buffer; while (*p == ' ') p ++; argv[argc ++] = p; for (; *p && argc < ARGS - 1; p ++) if (*p == ' ') { *p = 0; p ++; while (*p == ' ') p ++; argv[argc ++] = p; } /* The last arg could be an empty string. */ if (*argv[argc - 1] == 0) argc --; argv[argc] = NULL; if (! argv[0]) continue; struct debug_command *cmd; struct debug_command *match = NULL; for (cmd = commands; cmd; cmd = cmd->next) if (strlen (argv[0]) == 1) /* A short name. */ { if (argv[0][0] == cmd->short_name) { match = cmd; break; } } else if (strncmp (argv[0], cmd->name, strlen (argv[0])) == 0) { if (match) { printf ("%s is ambiguous. Could be %s or %s", argv[0], match->name, cmd->name); continue; } match = cmd; } if (! match) printf ("Unknown command: %s", argv[0]); else match->function (argc, argv); } return; }