--- freem/src/mdebug.c 2025/01/19 02:04:04 1.1 +++ freem/src/mdebug.c 2025/04/30 14:41:03 1.6 @@ -1,23 +1,11 @@ /* - * * - * * * - * * * - * *************** - * * * * * - * * MUMPS * - * * * * * - * *************** - * * * - * * * - * * - * - * mdebug.c + * $Id: mdebug.c,v 1.6 2025/04/30 14:41:03 snw Exp $ * debugger enhancements * * - * Author: Serena Willis + * Author: Serena Willis * Copyright (C) 1998 MUG Deutschland - * Copyright (C) 2020 Coherent Logic Development LLC + * Copyright (C) 2020, 2025 Coherent Logic Development LLC * * * This file is part of FreeM. @@ -35,11 +23,57 @@ * You should have received a copy of the GNU Affero Public License * along with FreeM. If not, see . * + * $Log: mdebug.c,v $ + * Revision 1.6 2025/04/30 14:41:03 snw + * Further debugger work + * + * Revision 1.5 2025/04/29 18:46:17 snw + * Begin work on interactive debugger + * + * Revision 1.4 2025/04/28 19:38:55 snw + * Add trace mode + * + * Revision 1.3 2025/03/09 19:50:47 snw + * Second phase of REUSE compliance and header reformat + * + * + * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC + * SPDX-License-Identifier: AGPL-3.0-or-later **/ #include #include #include +#include + +#include "config.h" + +#ifdef HAVE_LIBREADLINE +# if defined(HAVE_READLINE_READLINE_H) +# include +# elif defined(HAVE_READLINE_H) +# include +# else /* !defined(HAVE_READLINE_H) */ +extern char *readline (); +# endif /* !defined(HAVE_READLINE_H) */ +/*char *cmdline = NULL;*/ +#else /* !defined(HAVE_READLINE_READLINE_H) */ + /* no readline */ +#endif /* HAVE_LIBREADLINE */ + +#ifdef HAVE_READLINE_HISTORY +# if defined(HAVE_READLINE_HISTORY_H) +# include +# elif defined(HAVE_HISTORY_H) +# include +# else /* !defined(HAVE_HISTORY_H) */ +extern void add_history (); +extern int write_history (); +extern int read_history (); +# endif /* defined(HAVE_READLINE_HISTORY_H) */ + /* no history */ +#endif /* HAVE_READLINE_HISTORY */ + #include "mpsdef.h" #include "mdebug.h" @@ -67,6 +101,137 @@ void dbg_init (void) } +int debugger (int entry_mode, char *curcode) +{ + +#if defined(HAVE_LIBREADLINE) + static int first_entry = TRUE; + static int stepmode = STEPMODE_NONE; + + char *dbg_buf; + char dbg_prompt[256]; + HIST_ENTRY **dbg_hist; + int dbg_hist_idx; + HIST_ENTRY *dbg_hist_ent; + char rouname_buf[256]; + char *savptr; + char *dbg_cmd; + int do_prompt = FALSE; + register int i; + + set_io (UNIX); + + if (first_entry) { + first_entry = FALSE; + + printf ("\nEntering debug mode; M commands unavailable.\n"); + printf ("Type 'exit' to return to direct mode; 'help' for help.\n\n"); + + do_prompt = TRUE; + } + else { + switch (entry_mode) { + + case DEBENTRY_CMD: + if (stepmode == STEPMODE_CMD) { + do_prompt = TRUE; + } + else { + do_prompt = FALSE; + } + + break; + + case DEBENTRY_LINE: + if (stepmode == STEPMODE_CMD || stepmode == STEPMODE_LINE) { + do_prompt = TRUE; + } + else { + do_prompt = FALSE; + } + + break; + + case DEBENTRY_BREAKPOINT: + do_prompt = TRUE; + break; + + case DEBENTRY_SIGINT: + break; + } + } + + + if (!do_prompt) return TRUE; + + while (1) { + + //stcpy (rouname_buf, rou_name); + getraddress (rouname_buf, nstx); + stcnv_m2c (rouname_buf); + + snprintf (dbg_prompt, sizeof (dbg_prompt) - 1, "%s $STACK=%d [DEBUG]> ", rouname_buf, nstx); + + if ((stepmode == STEPMODE_LINE) || (stepmode == STEPMODE_CMD)) { + char codbuf[512]; + stcpy (codbuf, curcode); + stcnv_m2c (codbuf); + + printf ("%s\n", codbuf); + } + dbg_buf = readline (dbg_prompt); + + if (!dbg_buf) continue; + + savptr = dbg_buf; + dbg_cmd = strtok_r (dbg_buf, " ", &savptr); + + if ((strcmp (dbg_cmd, "exit") == 0) || (strcmp (dbg_cmd, "quit") == 0)) { + first_entry = TRUE; + stepmode = STEPMODE_NONE; + printf ("\n\nExiting debug mode.\n\n"); + set_io (MUMPS); + return FALSE; + } + else if ((strcmp (dbg_cmd, "step") == 0) || (strcmp (dbg_cmd, "s") == 0)) { + stepmode = STEPMODE_CMD; + return TRUE; + } + else if ((strcmp (dbg_cmd, "next") == 0) || (strcmp (dbg_cmd, "n") == 0)) { + stepmode = STEPMODE_LINE; + return TRUE; + } + else if ((strcmp (dbg_cmd, "continue") == 0) || (strcmp (dbg_cmd, "cont") == 0) || (strcmp(dbg_cmd, "c") == 0)) { + stepmode = STEPMODE_CONT; + return TRUE; + } + else if ((strcmp (dbg_cmd, "backtrace") == 0) || (strcmp (dbg_cmd, "bt") == 0)) { + char tmpbuf[256]; + + printf ("%-10s%s\n", "$STACK", "(CMND)ENTRY"); + printf ("%-10s%s\n", "======", "==========="); + + + for (i = 1; i <= nstx; i++) getraddress (callerr[i], i); + for (i = nstx; i > 0; i--) { + stcpy (tmpbuf, callerr[i]); + stcnv_m2c (tmpbuf); + printf ("%-10d%s\n", i, tmpbuf); + } + } + else { + printf ("DEBUG: invalid command\r\n"); + } + + } + + return TRUE; +#else + return FALSE; +#endif + +} + dbg_watch *dbg_add_watch (char *varnam) { register int i; @@ -243,5 +408,5 @@ void dbg_fire_watch (char *varnam) { w->chgct++; w->firect++; dbg_pending_watches++; - + }