nethack has detected an internal error; try to give a trace of call stack */
| 643 | /* nethack has detected an internal error; try to give a trace of call stack |
| 644 | */ |
| 645 | void |
| 646 | vms_traceback(int how) /* 1: exit after traceback; 2: stay in debugger */ |
| 647 | { |
| 648 | /* assumes that a static initializer applies to the first union |
| 649 | field and that no padding will be placed between len and str */ |
| 650 | union dbgcmd { |
| 651 | struct ascic { |
| 652 | unsigned char len; /* 8-bit length prefix */ |
| 653 | char str[79]; /* could be up to 255, but we don't need so much */ |
| 654 | } cmd_fields; |
| 655 | char cmd[1 + 79]; |
| 656 | }; |
| 657 | #define DBGCMD(arg) { (unsigned char) (sizeof arg - sizeof ""), arg } |
| 658 | static union dbgcmd dbg[3] = { |
| 659 | /* prologue for less verbose feedback (when combined with |
| 660 | $ define/User_mode dbg$output _NL: ) */ |
| 661 | DBGCMD("set Log SYS$OUTPUT: ; set Output Log,noTerminal,noVerify"), |
| 662 | /* enable modules with calls present on stack, then show those calls; |
| 663 | limit traceback to 18 stack frames to avoid scrolling off screen |
| 664 | (could check termcap LI and maybe give more, but we're operating |
| 665 | in a last-gasp environment so apply the KISS principle...) */ |
| 666 | DBGCMD("set Module/Calls ; show Calls 18"), |
| 667 | /* epilogue; "exit" ends the sequence it's part of, but it doesn't |
| 668 | seem able to cause program termination when used separately; |
| 669 | instead of relying on it, we'll redirect debugger input to come |
| 670 | from the null device so that it'll get an end-of-input condition |
| 671 | when it tries to get a command from the user */ |
| 672 | DBGCMD("exit"), |
| 673 | }; |
| 674 | #undef DBGCMD |
| 675 | |
| 676 | /* |
| 677 | * If we've been linked /noTraceback then we can't provide any |
| 678 | * trace of the call stack. Linking that way is required if |
| 679 | * nethack.exe is going to be installed with privileges, so the |
| 680 | * SECURE configuration usually won't have any trace feedback. |
| 681 | */ |
| 682 | if (!debuggable) { |
| 683 | ; /* debugger not available to catch lib$signal(SS$_DEBUG) */ |
| 684 | } else if (how == 2) { |
| 685 | /* omit prologue and epilogue (dbg[0] and dbg[2]) */ |
| 686 | (void) lib$signal(SS$_DEBUG, 1, dbg[1].cmd); |
| 687 | } else if (how == 1) { |
| 688 | /* |
| 689 | * Suppress most of debugger's initial feedback to avoid scaring |
| 690 | * users (and scrolling panic message off the screen). Also control |
| 691 | * debugging environment to try to prevent unexpected complications. |
| 692 | */ |
| 693 | /* start up with output going to /dev/null instead of stdout; |
| 694 | once started, output is sent to log file that's actually stdout */ |
| 695 | (void) vms_define("DBG$OUTPUT", "_NL:", 0); |
| 696 | /* take input from null device so debugger will see end-on-input |
| 697 | and quit if/when it tries to get a command from the user */ |
| 698 | (void) vms_define("DBG$INPUT", "_NL:", 0); |
| 699 | /* bypass any debugger initialization file the user might have */ |
| 700 | (void) vms_define("DBG$INIT", "_NL:", 0); |
| 701 | /* force tty interface by suppressing DECwindows/Motif interface */ |
| 702 | (void) vms_define("DBG$DECW$DISPLAY", " ", 0); |
no test coverage detected