Dec 072017
 
Method to make QBASIC 4.5 return specified Return Codes when program terminates. Maintains QBasic's clean up of vectors, and gives a -1 return code if termination is due to runtime errors. Patching involved.
File QBTERM2.ZIP from The Programmer’s Corner in
Category BASIC Language
Method to make QBASIC 4.5 return specified Return Codes when program terminates. Maintains QBasic’s clean up of vectors, and gives a -1 return code if termination is due to runtime errors. Patching involved.
File Name File Size Zip Size Zip Type
AEXIT.ASM 661 382 deflated
AEXIT.OBJ 493 418 deflated
AEXIT.QLB 5193 3147 deflated
EEXIT.ASM 123 92 deflated
EEXIT.OBJ 231 208 deflated
INFO.TXT 5398 2230 deflated
MOD.TXT 3700 1655 deflated
TESTENV.BAS 312 191 deflated
TESTEXE.BAS 340 201 deflated
TPCREAD.ME 199 165 deflated

Download File QBTERM2.ZIP Here

Contents of the INFO.TXT file


METHOD to enable QBASIC 4.5 to return a RETURN CODE on TERMINATION
==================================================================
Revision 2
Added AEXIT.ASM, AEXIT.OBJ & AEXIT.QLB
Support for EEXIT when in the QBASIC ENVIRONMENT
(provided you can include AEXIT.OBJ in your QLB ....
ie you have the corresponding LIB)


See (3)

----------------------------------------------------------------

(1) Patch BCOM45.lib

Since we are now going to END our Q-BASIC programs with our own
specified RETURN CODE, we need to change Q-BASIC's default RETURN CODE
from 0 to FF.
Thereafter, we will get this return code if our STAND-ALONE EXE program
exits with a run-time error (ie divide by zero etc)



B$END:
CALLB$END+b
XORAX,AX
PUSHAX
CALL_exit

Change XOR AX,AX to MOV AL,FFh;Default Return Code
(33C0 to B0FF )

In my copy of BCOM45.LIB, this was 1B0FC offset from the start of file

ie 1BOFC=33 ===> B0
1B0FD=C0 ===> FF


(2) Now we need a way to call _exit, and to pass it our required return code.

(Note: _exit is the exit routine in BCOM45.LIB that will clean up after
QBASIC and then terminate the program)

This gets a little complicated due to the QBASIC environment.
When working in the QBASIC Environment, we want to be able to see the Return
Code displayed, and we no NOT want to call _exit (which would TERMINATE the
Q-BASIC Environment and return us to DOS !)

When we COMPILE & LINK to make a STAND-ALONE QBASIC Program, we do not
necessarly want to DISPLAY a RETURN CODE message, but we DO want to call
_exit and have our specified return code.

Looking at the STAND ALONE program case first:

Since we cannot call _exit directly and pass our Return Code to it, we need
a very small ASSEMBLY CODE routine called EEXIT.

Our QBASIC program will look like this:

DECLARE SUB EEXIT(BYVAL retcode AS INTEGER)
....
program
....
EEXIT(5) {or EEXIT(a%)}

No need for an END.
Note END will return our -1 return code !!!!

EEXIT.ASM and EEXIT.OBJ are supplied with this package.

EEXIT.ASM is a simple program to JUMP to _exit

_exit expects an INTEGER to be passed by VALUE to it, and will use
this as the RETURN CODE.... (GREAT !!! Just what we want !)

All that is needed is to ADD the object module EEXIT.OBJ to BCOM45.lib
using the LIB.EXE program.

ie
LIB BCOM45
command: +EEXIT
list:
output lib:

THATS IT !!!!!

Note: You must make the STAND ALONE program from the DOS prompt level, using
(at last) BCOM45.lib as a library module.

----------------------------------------------------------

In the QBASIC ENVIRONMENT we will not be using BCOM45.LIB, so we need
a temporary LOCAL SUB called EEXIT while de-bugging or program.

An example follows:

DECLARE SUB EEXIT(retcode AS INTEGER)

...........
program
..........
EEXIT(5)


SUB EEXIT(rc%)
PRINT "Return Code is :";rc%
SLEEP 2
END SUB


Note that in the DECLARATION, retcode is NOT passed by VALUE, and the
addition of the LOCAL EEXIT sub.

The BYVAL must be ADDED, and the LOCAL SUB deleted when it comes time to make
the STAND ALONE program.

....................................................................

OK.... so the above is not very "CLEAN", but it DOES WORK !!!!
What is more important is that
(a) You get your desired return code
(b) You get -1 if you get a run-time error which is better than
the default 0 !!!
(c) QBASIC's CLEAN-UP housekeeping is maintained.
(just calling INT 21h with ah=4C does NOT !!!!)
(d) Within the QBASIC Environment, you get to see a display of
your RETURN Code as the program terminates.


**** PLEASE **** If you know a better way of doing this, or have any
suggestions for improving the method, let us all know !!!!

-------------------------- ENJOY ------------------------------


REVISION 2
==========

You can save having to modify your BASIC program to support EEXIT when
in the QBASIC ENVIRONMENT by including AEXIT.OBJ in your QLB
(assuming you can add it !!! ie Have the LIB)

AEXIT.OBJ is an ASM SUB that will display the Return Code, and is called
in exactly the same way (BYVAL) as EEXIT.OBJ, the code for use with a
STAND ALONE BASIC EXE program.

Note: Both EEXIT.OBJ & AEXIT.OBJ are ASM SUBs called EEXIT.

The difference is that EEXIT.OBJ terminates the program with the Return Code
being passed back to DOS, while AEXIT.OBJ displays the Return Code on the
Screen and does not Terminate the QBASIC Environment session.


Summary:
If you are able to add OBJs to your QLB then
(a) Add AEXIT.OBJ to your QLB
(b) Add EEXIT.OBJ to your BCOM45.LIB
(c) Patch BCOM45.lib if you want runtime errors to report -1
If you don't mind runtime errors of 0, don't bother to patch.
(d) Use the Definition
DEFINE SUB EEXIT(byval retcode as INTEGER)
(e) Within your basic program use EEXIT(returncode%) instead
of END or SYSTEM

If you can't add OBJs to your QLB (& need to use an existing QLB)
then read (1) & (2).

If you are not using a QLB, use AEXIT.QLB (QLB containing AEXIT.OBJ)

------------------------------------------------------------------------






 December 7, 2017  Add comments

Leave a Reply