Annotation of freem/src/mdebug.c, revision 1.5
1.1 snw 1: /*
1.5 ! snw 2: * $Id: mdebug.c,v 1.4 2025/04/28 19:38:55 snw Exp $
1.1 snw 3: * debugger enhancements
4: *
5: *
1.2 snw 6: * Author: Serena Willis <snw@coherent-logic.com>
1.1 snw 7: * Copyright (C) 1998 MUG Deutschland
1.3 snw 8: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
1.1 snw 9: *
10: *
11: * This file is part of FreeM.
12: *
13: * FreeM is free software: you can redistribute it and/or modify
14: * it under the terms of the GNU Affero Public License as published by
15: * the Free Software Foundation, either version 3 of the License, or
16: * (at your option) any later version.
17: *
18: * FreeM is distributed in the hope that it will be useful,
19: * but WITHOUT ANY WARRANTY; without even the implied warranty of
20: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21: * GNU Affero Public License for more details.
22: *
23: * You should have received a copy of the GNU Affero Public License
24: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
25: *
1.4 snw 26: * $Log: mdebug.c,v $
1.5 ! snw 27: * Revision 1.4 2025/04/28 19:38:55 snw
! 28: * Add trace mode
! 29: *
1.4 snw 30: * Revision 1.3 2025/03/09 19:50:47 snw
31: * Second phase of REUSE compliance and header reformat
32: *
1.3 snw 33: *
34: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
35: * SPDX-License-Identifier: AGPL-3.0-or-later
1.1 snw 36: **/
37:
38: #include <stdio.h>
39: #include <stdlib.h>
40: #include <string.h>
1.5 ! snw 41: #include <unistd.h>
! 42:
! 43: #include "config.h"
! 44:
! 45: #ifdef HAVE_LIBREADLINE
! 46: # if defined(HAVE_READLINE_READLINE_H)
! 47: # include <readline/readline.h>
! 48: # elif defined(HAVE_READLINE_H)
! 49: # include <readline.h>
! 50: # else /* !defined(HAVE_READLINE_H) */
! 51: extern char *readline ();
! 52: # endif /* !defined(HAVE_READLINE_H) */
! 53: /*char *cmdline = NULL;*/
! 54: #else /* !defined(HAVE_READLINE_READLINE_H) */
! 55: /* no readline */
! 56: #endif /* HAVE_LIBREADLINE */
! 57:
! 58: #ifdef HAVE_READLINE_HISTORY
! 59: # if defined(HAVE_READLINE_HISTORY_H)
! 60: # include <readline/history.h>
! 61: # elif defined(HAVE_HISTORY_H)
! 62: # include <history.h>
! 63: # else /* !defined(HAVE_HISTORY_H) */
! 64: extern void add_history ();
! 65: extern int write_history ();
! 66: extern int read_history ();
! 67: # endif /* defined(HAVE_READLINE_HISTORY_H) */
! 68: /* no history */
! 69: #endif /* HAVE_READLINE_HISTORY */
! 70:
1.1 snw 71:
72: #include "mpsdef.h"
73: #include "mdebug.h"
74: #include "freem.h"
75: #include "mref.h"
76:
77: dbg_watch dbg_watchlist[MAXWATCH]; /* list of watchpoints */
78: short dbg_enable_watch; /* 0 = watches disabled, 1 = watches enabled */
79: int dbg_pending_watches;
80:
81:
82: void dbg_init (void)
83: {
84: register int i;
85:
86: dbg_enable_watch = 0;
87: dbg_pending_watches = 0;
88:
89: for (i = 0; i < MAXWATCH; i++) {
90:
91: dbg_watchlist[i].varnam = NULL;
92: dbg_watchlist[i].chgct = 0;
93:
94: }
95:
96: }
97:
1.5 ! snw 98: int debugger (void)
! 99: {
! 100:
! 101: #if defined(HAVE_LIBREADLINE)
! 102: static int first_entry = TRUE;
! 103: char *dbg_buf;
! 104: char dbg_prompt[256];
! 105: HIST_ENTRY **dbg_hist;
! 106: int dbg_hist_idx;
! 107: HIST_ENTRY *dbg_hist_ent;
! 108: char rouname_buf[256];
! 109:
! 110: set_io (UNIX);
! 111:
! 112: if (first_entry) {
! 113: first_entry = FALSE;
! 114:
! 115: printf ("\nEntering debug mode; M commands unavailable.\n");
! 116: printf ("Type 'exit' to return to direct mode; 'help' for help.\n\n");
! 117: }
! 118:
! 119: while (1) {
! 120: stcpy (rouname_buf, rou_name);
! 121: stcnv_m2c (rouname_buf);
! 122:
! 123: snprintf (dbg_prompt, sizeof (dbg_prompt) - 1, "%s $STACK=%d [DEBUG]> ", rouname_buf, nstx);
! 124:
! 125: dbg_buf = readline (dbg_prompt);
! 126:
! 127: if (!dbg_buf) continue;
! 128:
! 129: if (strcmp (dbg_buf, "exit") == 0) {
! 130: first_entry = TRUE;
! 131: printf ("\n\nExiting debug mode.\n\n");
! 132: set_io (MUMPS);
! 133: return FALSE;
! 134: }
! 135: else {
! 136: printf ("DEBUG: invalid command\r\n");
! 137: }
! 138:
! 139: }
! 140:
! 141: return TRUE;
! 142: #else
! 143: return FALSE;
! 144: #endif
! 145:
! 146: }
! 147:
1.1 snw 148: dbg_watch *dbg_add_watch (char *varnam)
149: {
150: register int i;
151: int index = -1;
152: short found = 0;
153: dbg_watch *w;
154:
155: if ((w = dbg_find_watch (varnam)) != NULL) {
156: set_io (UNIX);
157: fprintf (stderr, "You are already watching '%s' (changed %d times).\n", dbg_get_watch_name (w->varnam), w->chgct);
158: set_io (MUMPS);
159: return NULL;
160: }
161:
162: for (i = 0; i < MAXWATCH; i++) {
163: if (dbg_watchlist[i].varnam == NULL) {
164: found++;
165: index = i;
166: break;
167: }
168: }
169:
170: if (!found) {
171: set_io (UNIX);
172: fprintf (stderr, "No free watchlist entries available. Try removing an existing watchpoint first.\n");
173: set_io (MUMPS);
174:
175: return NULL;
176: }
177:
178: if ((dbg_watchlist[index].varnam = (char *) malloc (256 * sizeof (char))) == NULL) {
179: set_io (UNIX);
180: fprintf (stderr, "Could not allocate memory for the new watchlist entry.\n");
181: set_io (MUMPS);
182:
183: return NULL;
184: }
185:
186: strcpy (dbg_watchlist[index].varnam, varnam);
187: dbg_watchlist[index].chgct = 0;
188:
189: set_io (UNIX);
190: fprintf (stderr, "Added '%s' to the watchlist.\n", dbg_get_watch_name (varnam));
191: set_io (MUMPS);
192:
193: return NULL;
194:
195: }
196:
197: void dbg_dump_watchlist (void)
198: {
199: register int i;
200:
201: for (i = 0; i < MAXWATCH; i++) {
202: if (dbg_watchlist[i].firect) {
203: dbg_dump_watch (dbg_watchlist[i].varnam);
204: }
205: }
206:
207: dbg_pending_watches = 0;
208: }
209:
210:
211: void dbg_remove_watch (char *varnam)
212: {
213: dbg_watch *w;
214:
215: if ((w = dbg_find_watch (varnam)) == NULL) {
216: set_io (UNIX);
217: fprintf (stderr, "'%s' is not being watched.\n", dbg_get_watch_name (varnam));
218: set_io (MUMPS);
219:
220: return;
221: }
222:
223: free (w->varnam);
224:
225: w->chgct = 0;
226: w->firect = 0;
227:
228: set_io (UNIX);
229: printf ("Removed '%s' from the watchlist.\n", dbg_get_watch_name (varnam));
230: set_io (MUMPS);
231:
232: return;
233: }
234:
235: void dbg_dump_watch (char *varnam)
236: {
237: char *ddwbuf;
238: dbg_watch *w;
239:
240: ddwbuf = (char *) malloc (STRLEN * sizeof (char));
241: NULLPTRCHK(ddwbuf,"dbg_dump_watch");
242:
243: if ((w = dbg_find_watch (varnam)) == NULL) {
244: set_io (UNIX);
245: fprintf (stderr, "'%s' is not being watched.\n", dbg_get_watch_name (varnam));
246: set_io (MUMPS);
247:
248: return;
249: }
250:
251: w->firect = 0;
252:
253: if (varnam[0] != '^') {
254: symtab (get_sym, varnam, ddwbuf);
255: }
256: else {
257: if (varnam[1] == '$') {
258: ssvn (get_sym, varnam, ddwbuf);
259: }
260: else {
261: global (get_sym, varnam, ddwbuf);
262: }
263: }
264:
265: stcnv_m2c (ddwbuf);
266:
267: set_io (UNIX);
268: printf (">> WATCHPOINT: %s => '%s' (changed %d times)\n", dbg_get_watch_name (varnam), ddwbuf, w->chgct);
269: set_io (MUMPS);
270:
271: free (ddwbuf);
272:
273: }
274:
275: dbg_watch *dbg_find_watch (char *varnam)
276: {
277: register int i;
278:
279:
280: for (i = 0; i < MAXWATCH; i++) {
281: if (dbg_watchlist[i].varnam != NULL) {
282: if (strcmp (varnam, dbg_watchlist[i].varnam) == 0) {
283: return &(dbg_watchlist[i]);
284: }
285:
286: }
287: }
288:
289: return NULL;
290: }
291:
292: char *dbg_get_watch_name (char *varnam)
293: {
294: freem_ref_t *r;
295: char *s;
296:
297: r = (freem_ref_t *) malloc (sizeof (freem_ref_t));
298: NULLPTRCHK(r,"dbg_get_watch_name");
299:
300: s = (char *) malloc (STRLEN * sizeof (char));
301: NULLPTRCHK(s,"dbg_get_watch_name");
302:
303: mref_init (r, MREF_RT_LOCAL, "");
304: internal_to_mref (r, varnam);
305: mref_to_external (r, s);
306:
307: free (r);
308:
309: return s;
310:
311: }
312:
313: void dbg_fire_watch (char *varnam) {
314:
315: dbg_watch *w;
316:
317: if ((w = dbg_find_watch (varnam)) == NULL) {
318: return;
319: }
320:
321: w->chgct++;
322: w->firect++;
323: dbg_pending_watches++;
1.4 snw 324:
1.1 snw 325: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>