Debugging BBj in the Console
BBj allows you to debug running programs, single step through the execution of the code, inspect variables and change their values, and even change the program code without interrupting your debug session. This article explains how to perform those actions.
The commands and principles described in this document apply to all BBj console types, e.g. using BBj inside a terminal emulator over Telnet or SSH, in the BBj SysConsole and TermConsole. Most of the commands are also available in the browser-based clients, the BUI MiniConsole and the DWC console. The details of implementation in the browser versions vary, and the output and interactivity may differ from the two other console types.
As a general rule, BASIS discourages debugging and editing code in live production environments. Even though BBj allows you to inspect and even edit programs directly (such as when an error occurs), changing code in live environments bears the risk of unwanted side effects, and can introduce new bugs into your code. Whenever possible, develop and debug your software in a dedicated development environment, and test it in a dedicated test environment before placing the new version in production. That being said, situations do arise where it becomes necessary to debug and fix code as it runs.
The Console
When you start a BBj interpreter, you are placed at the console. You can recognize the console by the command prompt “>”. After the command prompt, you can enter commands that execute immediately:
>PRINT "Hello"
Hello
>
To quit a running interpreter from the command prompt, type BYE or RELEASE and hit the Enter key.
Breaking to Console
There are a few ways to break out to the console from a running BBj program. Depending on the client's environment, you can perform the following steps:
-
In a terminal emulator, you can hit Ctrl-C, Ctrl-Break, or ESC, depending on the setting in the shell. (Hint: The stty intr setting and the actual terminal emulator product determine the key to use.)
-
In a SysWindow (the character-based console window in GUI that replaced the terminal emulator), you can click the “close window” icon (in Windows, the Cross or “X” in the top-right corner or the red stoplight button in the top left corner on macOS) to interrupt program execution.
-
In a GUI program, you can hit Ctrl-Break in the GUI Window that has focus to interrupt the program.
In all environments, putting the ESCAPE verb into the program code before executing will stop program execution at the location of the ESCAPE verb.
Warning: Don’t forget to remove any ESCAPEs before deploying a program to production.
And finally, any untrapped error will cause the program to drop to the console. If console access is disallowed by security settings, an untrapped error will terminate the session.
Disabling the Console
BBj provides settings to prevent the user from breaking into the console. This is especially important when deploying programs to production systems, mainly when available to the broader public.
The “Disallow Console” setting in the Enterprise Manager’s BBj Thin Client settings will effectively terminate the interpreter session whenever it attempts to drop to the console, no matter the reason. This control can also be turned on or off programmatically via the BBjAppServer::setDisallowConsole() method.
The SETESC verb can be used in program code to register a label or method executed whenever the user presses one of the keys to interrupt a program. Including SETESC in each program is highly recommended to handle program interruption by users gracefully.
The STBL("!CONPASS") and its siblings can be used to configure a console password. The user must enter the configured password before the console is displayed.
From BBj 19 onward, the optional console logging feature can record any interaction with the console. This feature is handy when the system is operated under regulatory rules, such as SOX or Basel II, where close monitoring of sensitive data manipulations is necessary by law.
Interacting with a Running Program in the Console
Consider the following program:
PRINT "Hello"
FOR I=1 TO 5
PRINT I
ESCAPE
NEXT
PRINT "Done."
When you run this program, it will stop at the ESCAPE:
Hello
1
ESCAPE
READY
>
You can type RUN to continue the execution until it hits ESCAPE again:
Hello
1
ESCAPE
READY
>RUN
2
ESCAPE
READY
>
To query the contents of the variable I, simply enter
>PRINT I
2
>
You can even modify I and continue execution:
>I=10
>run
Done.
READY
>
In this last example, the variable I has been changed to 10, which causes the program to exit the loop upon its next iteration.
Stepwise Execution
The BBj console allows developers to step line-by-line through a program after it has stopped at the console. To execute the program this way, RUN the previous program again and then enter a dot (period, “.”) followed by the RETURN key. The program will continue execution one line at a time, statement by statement:
>end
READY
>run
Hello
1
ESCAPE
READY
>.
NEXT I
>.
FOR I=1 TO 5
>.
PRINT I
>.
2
ESCAPE
>
The dot command optionally takes additional instructions. Adding an integer n after the dot will instruct the interpreter to execute the next n lines of the current program:
READY
>. 20
NEXT I
FOR I=1 TO 5
PRINT I
2
ESCAPE
ESCAPE
>
In this case, it did not execute 20 lines before stopping as it hit the ESCAPE command again.
It's also possible to issue two dots in a row, e.g., "..", optionally followed by an integer n. These double-dot statements tell the interpreter to execute the next line or lines of the program, except that it will step over any CALL, GOSUB, or CustomObject method.
While in a method in a BBj class, you can execute methodret to exit early or force a return value.
See Dot-commands and Single Step Command for more information on dot-stepping.
Search in the current program
You can scan for a search string in the current program by typing a backslash followed by the string to search:
>\PRINT
[1] PRINT "Hello"
https://documentation.basis.cloud/BASISHelp/WebHelp/usr/BBj_Enhancements/Dot_Commands.htm
Interacting with Variables
While in the console, you can query and set variables that are used by the program in memory. Use PRINT or ? to query the content of a variable, or assign new values with “=”:
>? name$
Smith
>name$="Baker"
>? name$
Baker
>
You can also execute methods on an object to learn more about it, for example:
? myVector!.size()
or
? myHashMap!.keySet().size().
DUMP
The DUMP verb outputs all variables to the console. You can redirect the output to a file:
>OPEN (7,MODE="O_CREATE,O_TRUNC")"mydump.txt"
>DUMP (7)
>CLOSE (7)
The file mydump.txt will contain the variables of the running program, including global variables. The DUMP verb accepts various options to reduce its output to variables of interest only, e.g., to show only variables in memory of the program in the current CALL stack level. You could type
dump (0,mode="vars,level="+str(tcb(13)))
https://documentation.basis.cloud/BASISHelp/WebHelp/commands/bbj-commands/dump_verb_bbj.htm
SETTRACE
Sometimes, it can be helpful for debugging purposes to record the sequence of commands. For that purpose, you can apply the SETTRACE verb, either directly in your program code or, like in this example, from the command line:
>OPEN (7,MODE="O_CREATE,O_TRUNC")"mytrace.txt"
>SETTRACE (7)
>RUN
2
ESCAPE
READY
>
The file mytrace.txt will contain all statements that have been executed. When you type RUN, the program execution will continue and be logged until the ENDTRACE verb is completed or the program itself terminates.
Using SETTRACE without a channel number pointing to a file will output the trace in the console after you continue to RUN the program.
Line Numbers
Packages developed with older versions of the BBx product family may contain line numbers. The BASIS Toolset offers a set of tools to convert this type of source code to a modern format that does not need line numbers.
Converting your line-numbered code to plain ASCII without line numbers improves maintenance when using modern IDE products such as Visual Studio Code and Eclipse. The code is also easily stored in version control systems like Git and SVN. Using a current format also makes it easier to track code changes, and any one of a variety of 'diff' tools can be used to compare versions, making it possible to tell who changed which part of the code and when they did so.
The BBj Code Formatter gives these denumbered programs a structure that improves the readability of your code.
While working with the console, you can use the DENUM verb to remove line numbers on the fly:
>load "test.src"
>list
0010 goto 20
0020 print (0,err=50) "hello"
0030 gosub 40
0040 END_LABEL: release
>DENUM
>list
goto L20
L20: print (0,err=L41) "hello"
gosub END_LABEL
END_LABEL: release
L41:
https://documentation.basis.cloud/BASISHelp/WebHelp/commands/denum_verb.htm
The opposite way is also possible: The RENUM verb will re-introduce line numbers to a program that has no line numbers:
>/
0010 PRINT "Hello"
0020 INPUT *
>DENUM
>/
PRINT "Hello"
INPUT *
>RENUM
>/
0010 PRINT "Hello"
0020 INPUT *
>
https://documentation.basis.cloud/BASISHelp/WebHelp/commands/renum_verb.htm
The line numbers make it easier to edit the program directly in the console. More information about editing programs in the console can be found under:
https://documentation.basis.cloud/BASISHelp/WebHelp/commands/edit_verb.htm
https://documentation.basis.cloud/BASISHelp/WebHelp/util/_edit_program_editor.htm
Warning: While it is technically possible to EDIT, SAVE and then continue to RUN a program in a live production system, e.g. in case of an error condition, we strongly recommend to not edit and persist your code directly in that environment. Always apply proper coding and testing standards!
Limitations
Logging variables without access to a console
Sometimes you need to debug in an environment where no console is available. To inspect or track variables during runtime, you can add statements to your program that log variables for later inspection:
-
Use System.out.println(myvar$) to output text to the BBj Debug…log located in the <bbj>/log directory.
-
Use mySysGui!.executeScript("console.log(...)") in the BUI or DWC client to log information in the browser console.
-
Using a MSGBOX(myvar$) can also be used for output, but is not silent. Don’t forget to remove that statement before deploying your code to production.
Stored Procedures and Triggers
Store Procedures and Triggers differ from traditional debugging. See
DEF FN Functions
Functions are an older concept of writing reusable code. This concept has been superseded by object orientation introduced in BBj a long time ago. However, existing applications may contain code that makes use of functions.
You can't dot-step through a multi-line function. That's not a big deal when they're working perfectly, but if they're not then it makes it a challenge to debug the code.
https://documentation.basis.cloud/BASISHelp/WebHelp/commands/def_verb.htm
Related Documentation
Various materials related to debugging a Business BASIC program are available online in the BASIS help system. See the following links for more detailed information on the concepts covered in this article.