|
|
| version 1.10, 2025/05/01 04:45:15 | version 1.12, 2025/05/01 21:02:31 |
|---|---|
| Line 24 | Line 24 |
| * along with FreeM. If not, see <https://www.gnu.org/licenses/>. | * along with FreeM. If not, see <https://www.gnu.org/licenses/>. |
| * | * |
| * $Log$ | * $Log$ |
| * Revision 1.12 2025/05/01 21:02:31 snw | |
| * Documentation updates | |
| * | |
| * Revision 1.11 2025/05/01 17:02:30 snw | |
| * Further debugging improvements | |
| * | |
| * Revision 1.10 2025/05/01 04:45:15 snw | * Revision 1.10 2025/05/01 04:45:15 snw |
| * Improve backtraces | * Improve backtraces |
| * | * |
| Line 113 void dbg_init (void) | Line 119 void dbg_init (void) |
| } | } |
| int debugger (int entry_mode, char *curcode) | int debugger (int entry_mode, char *entryref) |
| { | { |
| #if defined(HAVE_LIBREADLINE) | #if defined(HAVE_LIBREADLINE) |
| Line 122 int debugger (int entry_mode, char *curc | Line 128 int debugger (int entry_mode, char *curc |
| char *dbg_buf; | char *dbg_buf; |
| char dbg_prompt[256]; | char dbg_prompt[256]; |
| int dbg_argc; | |
| HIST_ENTRY **dbg_hist; | HIST_ENTRY **dbg_hist; |
| int dbg_hist_idx; | int dbg_hist_idx; |
| HIST_ENTRY *dbg_hist_ent; | HIST_ENTRY *dbg_hist_ent; |
| char rouname_buf[256]; | char rouname_buf[256]; |
| char *savptr; | char *savptr; |
| char *dbg_cmd; | char *dbg_cmd; |
| char *dbarg; | |
| int do_prompt = FALSE; | int do_prompt = FALSE; |
| char cur_code[512]; | |
| char tbuf[512]; | |
| char tbuf2[512]; | |
| register int i; | register int i; |
| register int j; | register int j; |
| Line 183 int debugger (int entry_mode, char *curc | Line 194 int debugger (int entry_mode, char *curc |
| stcpy (rouname_buf, rou_name); | stcpy (rouname_buf, rou_name); |
| } | } |
| else { | else { |
| char tbuf[256]; | |
| getraddress (tbuf, nstx); | getraddress (tbuf, nstx); |
| stcpy (rouname_buf, &(tbuf[3])); | stcpy (rouname_buf, &(tbuf[3])); |
| } | } |
| stcnv_m2c (rouname_buf); | stcnv_m2c (rouname_buf); |
| snprintf (dbg_prompt, sizeof (dbg_prompt) - 1, "%s $STACK=%d [DEBUG]> ", rouname_buf, nstx); | if (stepmode != STEPMODE_NONE) { |
| getraddress (tbuf, nstx); | |
| stcnv_m2c (tbuf); | |
| strcpy (tbuf2, &(tbuf[3])); | |
| routine_get_line (tbuf2, cur_code); | |
| if ((stepmode == STEPMODE_LINE) || (stepmode == STEPMODE_CMD)) { | printf ("%s\n", cur_code); |
| char codbuf[512]; | |
| stcpy (codbuf, curcode); | |
| stcnv_m2c (codbuf); | |
| printf ("%s\n", codbuf); | |
| } | } |
| snprintf (dbg_prompt, sizeof (dbg_prompt) - 1, "%s $STACK=%d [DEBUG]> ", rouname_buf, nstx); | |
| if (dbg_enable_watch && dbg_pending_watches) dbg_dump_watchlist (); | |
| dbg_buf = readline (dbg_prompt); | dbg_buf = readline (dbg_prompt); |
| if (!dbg_buf) continue; | if (!dbg_buf) continue; |
| if (strlen (dbg_buf) < 1) continue; | |
| dbg_argc = 1; | |
| for (i = 0; i < strlen (dbg_buf); i++) { | |
| if (dbg_buf[i] == ' ') dbg_argc++; | |
| } | |
| dbarg = dbg_buf; | |
| savptr = dbg_buf; | savptr = dbg_buf; |
| dbg_cmd = strtok_r (dbg_buf, " ", &savptr); | dbg_cmd = strtok_r (dbg_buf, " ", &savptr); |
| dbarg += strlen (dbg_cmd) + 1; | |
| if ((strcmp (dbg_cmd, "exit") == 0) || (strcmp (dbg_cmd, "quit") == 0)) { | if ((strcmp (dbg_cmd, "exit") == 0) || (strcmp (dbg_cmd, "quit") == 0)) { |
| first_entry = TRUE; | first_entry = TRUE; |
| stepmode = STEPMODE_NONE; | stepmode = STEPMODE_NONE; |
| Line 213 int debugger (int entry_mode, char *curc | Line 232 int debugger (int entry_mode, char *curc |
| set_io (MUMPS); | set_io (MUMPS); |
| return FALSE; | return FALSE; |
| } | } |
| else if ((strcmp (dbg_cmd, "examine") == 0) || (strcmp (dbg_cmd, "e") == 0)) { | |
| char *glvn; | |
| char key[STRLEN]; | |
| char res[STRLEN]; | |
| if (dbg_argc < 2) { | |
| printf ("debug: syntax error\n"); | |
| } | |
| else { | |
| glvn = dbarg; | |
| name_to_key (key, glvn, STRLEN - 1); | |
| if (key[0] != '^') { | |
| symtab (get_sym, key, res); | |
| } | |
| else { | |
| if (key[1] != '$') { | |
| global (get_sym, key, res); | |
| } | |
| else { | |
| ssvn (get_sym, key, res); | |
| } | |
| } | |
| if (merr () != OK) { | |
| if (merr () == M6) { | |
| printf ("examine: local variable %s is not defined\n", glvn); | |
| merr_clear (); | |
| } | |
| else if (merr () == M7) { | |
| printf ("examine: global variable %s is not defined\n", glvn); | |
| merr_clear (); | |
| } | |
| else { | |
| printf ("examine: error retrieving %s\n", glvn); | |
| merr_clear (); | |
| } | |
| } | |
| else { | |
| stcnv_m2c (res); | |
| printf ("%s=\"%s\"\n", glvn, res); | |
| } | |
| } | |
| } | |
| else if ((strcmp (dbg_cmd, "trace") == 0) || (strcmp (dbg_cmd, "t") == 0)) { | |
| if (trace_mode == 0) { | |
| trace_mode = 1; | |
| printf ("debug: trace on\n"); | |
| } | |
| else { | |
| trace_mode = 0; | |
| printf ("debug: trace off\n"); | |
| } | |
| ssvn_job_update (); | |
| } | |
| else if ((strcmp (dbg_cmd, "step") == 0) || (strcmp (dbg_cmd, "s") == 0)) { | else if ((strcmp (dbg_cmd, "step") == 0) || (strcmp (dbg_cmd, "s") == 0)) { |
| stepmode = STEPMODE_CMD; | stepmode = STEPMODE_CMD; |
| return TRUE; | return TRUE; |
| Line 276 int debugger (int entry_mode, char *curc | Line 350 int debugger (int entry_mode, char *curc |
| printf ("ZTRAP:\t%s\n", ecbuf); | printf ("ZTRAP:\t%s\n", ecbuf); |
| } | } |
| else if ((strcmp (dbg_cmd, "halt") == 0) || (strcmp (dbg_cmd, "h") == 0)) { | |
| printf ("debug: forcing halt\n"); | |
| exit (0); | |
| } | |
| else if ((strcmp (dbg_cmd, "watch") == 0) || (strcmp (dbg_cmd, "w") == 0)) { | |
| char watchmode; | |
| char *glvn; | |
| if (dbg_argc == 1) { | |
| switch (dbg_enable_watch) { | |
| case 0: | |
| dbg_enable_watch = 1; | |
| printf ("debug: watchpoints enabled\n"); | |
| break; | |
| case 1: | |
| dbg_enable_watch = 0; | |
| printf ("debug: watchpoints disabled\n"); | |
| break; | |
| } | |
| } | |
| else { | |
| watchmode = dbarg[0]; | |
| glvn = &(dbarg[1]); | |
| switch (watchmode) { | |
| case '+': | |
| dbg_add_watch (glvn); | |
| break; | |
| case '-': | |
| dbg_remove_watch (glvn); | |
| break; | |
| case '?': | |
| dbg_dump_watch (glvn); | |
| break; | |
| default: | |
| printf ("debug: watch mode must be +, -, or ?\n"); | |
| break; | |
| } | |
| set_io (UNIX); | |
| } | |
| } | |
| else { | else { |
| printf ("DEBUG: invalid command\r\n"); | printf ("DEBUG: invalid command\r\n"); |
| } | } |
| Line 319 dbg_watch *dbg_add_watch (char *varnam) | Line 435 dbg_watch *dbg_add_watch (char *varnam) |
| return NULL; | return NULL; |
| } | } |
| if ((dbg_watchlist[index].varnam = (char *) malloc (256 * sizeof (char))) == NULL) { | if ((dbg_watchlist[index].varnam = (char *) calloc (256, sizeof (char))) == NULL) { |
| set_io (UNIX); | set_io (UNIX); |
| fprintf (stderr, "Could not allocate memory for the new watchlist entry.\n"); | fprintf (stderr, "Could not allocate memory for the new watchlist entry.\n"); |
| set_io (MUMPS); | set_io (MUMPS); |
| Line 331 dbg_watch *dbg_add_watch (char *varnam) | Line 447 dbg_watch *dbg_add_watch (char *varnam) |
| dbg_watchlist[index].chgct = 0; | dbg_watchlist[index].chgct = 0; |
| set_io (UNIX); | set_io (UNIX); |
| fprintf (stderr, "Added '%s' to the watchlist.\n", dbg_get_watch_name (varnam)); | fprintf (stderr, "Added '%s' to the watchlist.\n", varnam); |
| set_io (MUMPS); | set_io (MUMPS); |
| return NULL; | return NULL; |
| Line 343 void dbg_dump_watchlist (void) | Line 459 void dbg_dump_watchlist (void) |
| register int i; | register int i; |
| for (i = 0; i < MAXWATCH; i++) { | for (i = 0; i < MAXWATCH; i++) { |
| if (dbg_watchlist[i].firect) { | if (dbg_watchlist[i].firect) { |
| dbg_dump_watch (dbg_watchlist[i].varnam); | dbg_dump_watch (dbg_watchlist[i].varnam); |
| } | } |
| } | } |
| dbg_pending_watches = 0; | dbg_pending_watches = 0; |
| Line 456 char *dbg_get_watch_name (char *varnam) | Line 572 char *dbg_get_watch_name (char *varnam) |
| void dbg_fire_watch (char *varnam) { | void dbg_fire_watch (char *varnam) { |
| dbg_watch *w; | dbg_watch *w; |
| if ((w = dbg_find_watch (varnam)) == NULL) { | if ((w = dbg_find_watch (varnam)) == NULL) { |
| return; | return; |
| } | } |
| w->chgct++; | w->chgct++; |
| w->firect++; | w->firect++; |
| dbg_pending_watches++; | dbg_pending_watches++; |
| } | } |