The GOSUB statement calls an internal subroutine.
The optional colon after the label has no effect on the action of the statement.
The program continues execution at the given label, saving the location of the GOSUB for a later RETURN which will resume execution at the statement following the GOSUB. See also the RETURN TO statement for details of alternate returns.
QMBasic defines two styles of internal subroutine. A conventional internal subroutine, as found in other multivalue database products, has no formal start or end. The label may be any label defined within the program or subroutine. It is the programmer's responsibility to ensure that internal subroutines return correctly. Variables referenced in the internal subroutine are accessible across the entire program module, requiring great care from the programmer to ensure that data in one part of the module is not accidentally altered elsewhere by use of the same name. Loop counters in FOR/NEXT loops are a good example of where this frequently happens. Calling this style of internal subroutine recursively is possible but of limited use because the variables in one invocation will be overwritten by the next.
The second style, referred to in QMBasic terminology as a local subroutine, is introduced by the LOCAL statement and is terminated by END. Local subroutines may have arguments and may have private local variables that are not visible outside the subroutine and which are stacked if the subroutine is called recursively. The PRIVATE statement(s) used to declare private variables must appear at the start of the local subroutine.
The argument list for a local subroutine may contain up to 255 items. If a subroutine has no arguments, the brackets may be omitted.
Each argument is
Where the argument is a reference to a variable, a matrix element or a whole matrix, the subroutine may update the values in these variables. Except when passing a whole matrix, the calling program can effectively prevent this by forcing the argument to be passed by value rather than by reference by enclosing it in brackets, thus making the argument into an expression.
IF STOCK.LEVEL <= REORDER.LEVEL THEN GOSUB REORDER
This program fragment checks if the value of STOCK.LEVEL has fallen to the REORDER.LEVEL and, if so, calls internal subroutine REORDER.
LOCAL SUBROUTINE UPDATE.STOCK(PROD.NO, CHANGE)
READU STOCK.REC FROM STOCK.F, PROD.NO THEN
STOCK.REC<STK.QOH> += CHANGE
WRITE STOCK.REC TO STOCK.F, PROD.NO
The above local subroutine takes a record id and the amount by which a field is to be updated, reads the corresponding record and applies the update. A real program would include statements to handle the case where the record is not found. The subroutine would be called using a statement such as
GOSUB UPDATE.STOCK(PART.ID, QTY)