558 lines
20 KiB
Text
558 lines
20 KiB
Text
# The MIT License (MIT)
|
|
#
|
|
# Copyright (C) 2026 Scott Duensing
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to
|
|
# deal in the Software without restriction, including without limitation the
|
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
# sell copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in
|
|
# all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
# IN THE SOFTWARE.
|
|
|
|
.section Libraries
|
|
.topic lib.basrt
|
|
.title BASIC Runtime Library
|
|
.toc 0 BASIC Runtime Library
|
|
.index BASIC Runtime
|
|
.index BasVmT
|
|
.index BasValueT
|
|
.index BasStringT
|
|
.index BasArrayT
|
|
.index BasModuleT
|
|
|
|
.h1 BASIC Runtime Library
|
|
|
|
Stack-based p-code virtual machine and value system for DVX BASIC. Embeddable: the host provides I/O and UI callbacks. No DVX GUI dependencies in the core runtime.
|
|
|
|
Headers: apps/dvxbasic/runtime/vm.h, apps/dvxbasic/runtime/values.h
|
|
|
|
.link lib.basrt.values Value System (values.h)
|
|
.link lib.basrt.vm Virtual Machine (vm.h)
|
|
|
|
.topic lib.basrt.values
|
|
.title Value System
|
|
.toc 1 Value System
|
|
.index BasValueT
|
|
.index BasStringT
|
|
.index BasArrayT
|
|
.index BasUdtT
|
|
.index basStringNew
|
|
.index basArrayNew
|
|
.index basValCopy
|
|
.index basValRelease
|
|
|
|
.h1 Value System
|
|
|
|
Tagged union value type for the VM evaluation stack, variables, and array elements. Strings, arrays, and UDT instances are reference-counted for automatic memory management without a garbage collector.
|
|
|
|
Header: apps/dvxbasic/runtime/values.h
|
|
|
|
.h2 Type Tags
|
|
|
|
.table
|
|
Constant Value C Union Field Description
|
|
-------- ----- ------------- -----------
|
|
BAS_TYPE_INTEGER 0 intVal 16-bit signed integer.
|
|
BAS_TYPE_LONG 1 longVal 32-bit signed integer.
|
|
BAS_TYPE_SINGLE 2 sngVal 32-bit float.
|
|
BAS_TYPE_DOUBLE 3 dblVal 64-bit float.
|
|
BAS_TYPE_STRING 4 strVal Reference-counted dynamic string.
|
|
BAS_TYPE_BOOLEAN 5 boolVal True (-1) or False (0).
|
|
BAS_TYPE_ARRAY 6 arrVal Reference-counted array.
|
|
BAS_TYPE_UDT 7 udtVal Reference-counted user-defined type.
|
|
BAS_TYPE_OBJECT 8 objVal Opaque host pointer (form, control).
|
|
BAS_TYPE_REF 9 refVal ByRef pointer to a BasValueT slot.
|
|
.endtable
|
|
|
|
.h2 BasValueT
|
|
|
|
Tagged union holding any BASIC value.
|
|
|
|
.code
|
|
struct BasValueTag {
|
|
uint8_t type; // BAS_TYPE_*
|
|
union {
|
|
int16_t intVal;
|
|
int32_t longVal;
|
|
float sngVal;
|
|
double dblVal;
|
|
BasStringT *strVal;
|
|
int16_t boolVal;
|
|
BasArrayT *arrVal;
|
|
BasUdtT *udtVal;
|
|
void *objVal;
|
|
BasValueT *refVal;
|
|
};
|
|
};
|
|
.endcode
|
|
|
|
.h2 Value Constructors
|
|
|
|
.code
|
|
BasValueT basValInteger(int16_t v);
|
|
BasValueT basValLong(int32_t v);
|
|
BasValueT basValSingle(float v);
|
|
BasValueT basValDouble(double v);
|
|
BasValueT basValString(BasStringT *s);
|
|
BasValueT basValStringFromC(const char *text);
|
|
BasValueT basValBool(bool v);
|
|
BasValueT basValObject(void *obj);
|
|
.endcode
|
|
|
|
Each returns a BasValueT with the appropriate type tag set. basValString increments the string's reference count.
|
|
|
|
.h2 Value Lifetime
|
|
|
|
.code
|
|
BasValueT basValCopy(BasValueT v);
|
|
void basValRelease(BasValueT *v);
|
|
.endcode
|
|
|
|
.table
|
|
Function Description
|
|
-------- -----------
|
|
basValCopy Copy a value. Increments reference count for strings, arrays, and UDTs.
|
|
basValRelease Release a value. Decrements reference count and frees if it reaches zero.
|
|
.endtable
|
|
|
|
.h2 Type Conversion
|
|
|
|
.code
|
|
BasValueT basValToInteger(BasValueT v);
|
|
BasValueT basValToLong(BasValueT v);
|
|
BasValueT basValToSingle(BasValueT v);
|
|
BasValueT basValToDouble(BasValueT v);
|
|
BasValueT basValToString(BasValueT v);
|
|
BasValueT basValToBool(BasValueT v);
|
|
.endcode
|
|
|
|
Each returns a new value of the target type. The original is not released; the caller manages both lifetimes.
|
|
|
|
.h2 Value Utilities
|
|
|
|
.table
|
|
Function Description
|
|
-------- -----------
|
|
basValToNumber(v) Convert any numeric value to double.
|
|
basValFormatString(v) Return a new ref-counted string representation of v.
|
|
basValIsTruthy(v) True if non-zero number or non-empty string.
|
|
basValCompare(a, b) Compare two values. Returns -1, 0, or 1.
|
|
basValCompareCI(a, b) Case-insensitive comparison (OPTION COMPARE TEXT).
|
|
basValPromoteType(a, b) Determine common type for binary ops (e.g. Integer + Single -> Single).
|
|
.endtable
|
|
|
|
.h2 BasStringT
|
|
|
|
Reference-counted string with flexible array member for inline storage.
|
|
|
|
.code
|
|
typedef struct {
|
|
int32_t refCount;
|
|
int32_t len;
|
|
int32_t cap;
|
|
char data[];
|
|
} BasStringT;
|
|
.endcode
|
|
|
|
.h3 String Functions
|
|
|
|
.table
|
|
Function Description
|
|
-------- -----------
|
|
basStringNew(text, len) Allocate from a C string. refCount starts at 1.
|
|
basStringAlloc(cap) Allocate an empty string with given capacity.
|
|
basStringRef(s) Increment reference count. Returns s.
|
|
basStringUnref(s) Decrement reference count. Frees when it reaches zero.
|
|
basStringConcat(a, b) Concatenate two strings. Returns a new string (refCount 1).
|
|
basStringSub(s, start, len) Extract a substring. Returns a new string (refCount 1).
|
|
basStringCompare(a, b) Compare. Returns <0, 0, >0 (like strcmp).
|
|
basStringCompareCI(a, b) Case-insensitive compare.
|
|
basStringSystemInit() Initialize the string system and empty string singleton.
|
|
basStringSystemShutdown() Shut down the string system.
|
|
.endtable
|
|
|
|
The global basEmptyString is a singleton that is never freed.
|
|
|
|
.h2 BasArrayT
|
|
|
|
Reference-counted multi-dimensional array (up to BAS_ARRAY_MAX_DIMS = 8 dimensions).
|
|
|
|
.code
|
|
typedef struct {
|
|
int32_t refCount;
|
|
uint8_t elementType;
|
|
int32_t dims;
|
|
int32_t lbound[BAS_ARRAY_MAX_DIMS];
|
|
int32_t ubound[BAS_ARRAY_MAX_DIMS];
|
|
int32_t totalElements;
|
|
BasValueT *elements;
|
|
} BasArrayT;
|
|
.endcode
|
|
|
|
.h3 Array Functions
|
|
|
|
.table
|
|
Function Description
|
|
-------- -----------
|
|
basArrayNew(dims, lbounds, ubounds, type) Allocate an array. refCount starts at 1.
|
|
basArrayFree(arr) Free all elements and release the array.
|
|
basArrayRef(arr) Increment reference count.
|
|
basArrayUnref(arr) Decrement reference count. Frees at zero.
|
|
basArrayIndex(arr, indices, ndims) Compute flat index from multi-dimensional indices. Returns -1 if out of bounds.
|
|
.endtable
|
|
|
|
.h2 BasUdtT
|
|
|
|
Reference-counted user-defined type instance.
|
|
|
|
.code
|
|
typedef struct {
|
|
int32_t refCount;
|
|
int32_t typeId;
|
|
int32_t fieldCount;
|
|
BasValueT *fields;
|
|
} BasUdtT;
|
|
.endcode
|
|
|
|
.h3 UDT Functions
|
|
|
|
.table
|
|
Function Description
|
|
-------- -----------
|
|
basUdtNew(typeId, fieldCount) Allocate a UDT instance. refCount starts at 1.
|
|
basUdtFree(udt) Free all fields and release.
|
|
basUdtRef(udt) Increment reference count.
|
|
basUdtUnref(udt) Decrement reference count. Frees at zero.
|
|
.endtable
|
|
|
|
.topic lib.basrt.vm
|
|
.title Virtual Machine
|
|
.toc 1 Virtual Machine
|
|
.index BasVmT
|
|
.index BasModuleT
|
|
.index BasVmResultE
|
|
.index basVmCreate
|
|
.index basVmRun
|
|
.index basVmStep
|
|
.index basVmDestroy
|
|
.index basVmCallSub
|
|
|
|
.h1 Virtual Machine
|
|
|
|
Stack-based p-code interpreter. Executes compiled BASIC bytecode modules. The host provides I/O, UI, SQL, and external library callbacks. The VM has no DVX dependencies; it can be embedded in any C program.
|
|
|
|
Header: apps/dvxbasic/runtime/vm.h
|
|
|
|
.h2 VM Limits
|
|
|
|
.table
|
|
Constant Value Description
|
|
-------- ----- -----------
|
|
BAS_VM_STACK_SIZE 256 Evaluation stack depth.
|
|
BAS_VM_CALL_STACK_SIZE 64 Maximum call nesting depth.
|
|
BAS_VM_MAX_GLOBALS 512 Global variable slots.
|
|
BAS_VM_MAX_LOCALS 64 Local variables per stack frame.
|
|
BAS_VM_MAX_FOR_DEPTH 32 Maximum nested FOR loop depth.
|
|
BAS_VM_MAX_FILES 16 Open file channels (1-based).
|
|
.endtable
|
|
|
|
.h2 BasVmResultE
|
|
|
|
Result codes returned by basVmRun and basVmStep.
|
|
|
|
.table
|
|
Code Value Description
|
|
---- ----- -----------
|
|
BAS_VM_OK 0 Program completed normally.
|
|
BAS_VM_HALTED 1 HALT instruction reached.
|
|
BAS_VM_YIELDED 2 DoEvents yielded control.
|
|
BAS_VM_ERROR 3 Runtime error.
|
|
BAS_VM_STACK_OVERFLOW 4 Evaluation stack overflow.
|
|
BAS_VM_STACK_UNDERFLOW 5 Evaluation stack underflow.
|
|
BAS_VM_CALL_OVERFLOW 6 Call stack overflow.
|
|
BAS_VM_DIV_BY_ZERO 7 Division by zero.
|
|
BAS_VM_TYPE_MISMATCH 8 Type mismatch in operation.
|
|
BAS_VM_OUT_OF_MEMORY 9 Memory allocation failed.
|
|
BAS_VM_BAD_OPCODE 10 Unknown opcode encountered.
|
|
BAS_VM_FILE_ERROR 11 File I/O error.
|
|
BAS_VM_SUBSCRIPT_RANGE 12 Array subscript out of range.
|
|
BAS_VM_USER_ERROR 13 ON ERROR raised by program.
|
|
BAS_VM_STEP_LIMIT 14 Step limit reached (not an error).
|
|
BAS_VM_BREAKPOINT 15 Breakpoint or step completed (not an error).
|
|
.endtable
|
|
|
|
.h2 Lifecycle
|
|
|
|
.code
|
|
BasVmT *basVmCreate(void);
|
|
void basVmDestroy(BasVmT *vm);
|
|
void basVmLoadModule(BasVmT *vm, BasModuleT *module);
|
|
void basVmReset(BasVmT *vm);
|
|
.endcode
|
|
|
|
.table
|
|
Function Description
|
|
-------- -----------
|
|
basVmCreate Allocate and initialize a new VM instance.
|
|
basVmDestroy Destroy the VM and free all resources.
|
|
basVmLoadModule Load a compiled module (BasModuleT) into the VM.
|
|
basVmReset Reset to initial state (clear stack, globals, PC).
|
|
.endtable
|
|
|
|
.h2 Execution
|
|
|
|
.code
|
|
BasVmResultE basVmRun(BasVmT *vm);
|
|
BasVmResultE basVmStep(BasVmT *vm);
|
|
void basVmSetStepLimit(BasVmT *vm, int32_t limit);
|
|
.endcode
|
|
|
|
.table
|
|
Function Description
|
|
-------- -----------
|
|
basVmRun Execute the loaded module until it ends, halts, yields, errors, or hits a breakpoint/step limit.
|
|
basVmStep Execute a single instruction and return. Useful for debugger stepping.
|
|
basVmSetStepLimit Set maximum instructions per basVmRun call. 0 = unlimited (default). Returns BAS_VM_STEP_LIMIT when reached.
|
|
.endtable
|
|
|
|
.h2 I/O Callbacks
|
|
|
|
The host provides these callbacks for PRINT, INPUT, and DoEvents statements.
|
|
|
|
.code
|
|
void basVmSetPrintCallback(BasVmT *vm, BasPrintFnT fn, void *ctx);
|
|
void basVmSetInputCallback(BasVmT *vm, BasInputFnT fn, void *ctx);
|
|
void basVmSetDoEventsCallback(BasVmT *vm, BasDoEventsFnT fn, void *ctx);
|
|
.endcode
|
|
|
|
.h3 Callback Types
|
|
|
|
.code
|
|
typedef void (*BasPrintFnT)(void *ctx, const char *text, bool newline);
|
|
typedef bool (*BasInputFnT)(void *ctx, const char *prompt,
|
|
char *buf, int32_t bufSize);
|
|
typedef bool (*BasDoEventsFnT)(void *ctx);
|
|
.endcode
|
|
|
|
.table
|
|
Type Description
|
|
---- -----------
|
|
BasPrintFnT Called for PRINT output. text is null-terminated. newline indicates line advance.
|
|
BasInputFnT Called for INPUT. Fill buf (up to bufSize-1 chars). Return true on success, false on cancel.
|
|
BasDoEventsFnT Called for DoEvents. Process pending events and return. Return false to stop the program.
|
|
.endtable
|
|
|
|
.h2 UI Callbacks
|
|
|
|
For form and control integration. The VM resolves all UI operations through these callbacks, keeping it independent of any specific GUI toolkit.
|
|
|
|
.code
|
|
void basVmSetUiCallbacks(BasVmT *vm, const BasUiCallbacksT *ui);
|
|
.endcode
|
|
|
|
.h3 BasUiCallbacksT
|
|
|
|
.table
|
|
Field Signature Description
|
|
----- --------- -----------
|
|
getProp BasValueT (*)(ctx, ctrlRef, propName) Get a control property value.
|
|
setProp void (*)(ctx, ctrlRef, propName, value) Set a control property.
|
|
callMethod BasValueT (*)(ctx, ctrlRef, methodName, args, argc) Call a method on a control.
|
|
createCtrl void *(*)(ctx, formRef, typeName, ctrlName) Create a control on a form.
|
|
findCtrl void *(*)(ctx, formRef, ctrlName) Find a control by name.
|
|
findCtrlIdx void *(*)(ctx, formRef, ctrlName, index) Find a control array element.
|
|
loadForm void *(*)(ctx, formName) Load a form by name.
|
|
unloadForm void (*)(ctx, formRef) Unload a form.
|
|
showForm void (*)(ctx, formRef, modal) Show a form (modal or modeless).
|
|
hideForm void (*)(ctx, formRef) Hide a form (keep in memory).
|
|
msgBox int32_t (*)(ctx, message, flags) Display a message box.
|
|
inputBox BasStringT *(*)(ctx, prompt, title, defaultText) Display an input box.
|
|
ctx void * User pointer passed to all callbacks.
|
|
.endtable
|
|
|
|
.h2 SQL Callbacks
|
|
|
|
For database integration.
|
|
|
|
.code
|
|
void basVmSetSqlCallbacks(BasVmT *vm, const BasSqlCallbacksT *sql);
|
|
.endcode
|
|
|
|
.h3 BasSqlCallbacksT
|
|
|
|
.table
|
|
Field Signature Description
|
|
----- --------- -----------
|
|
sqlOpen int32_t (*)(path) Open a database. Returns handle.
|
|
sqlClose void (*)(db) Close a database.
|
|
sqlExec bool (*)(db, sql) Execute a non-query SQL statement.
|
|
sqlError const char *(*)(db) Get last error message.
|
|
sqlQuery int32_t (*)(db, sql) Execute a query. Returns result set handle.
|
|
sqlNext bool (*)(rs) Advance to next row.
|
|
sqlEof bool (*)(rs) Check if at end of result set.
|
|
sqlFieldCount int32_t (*)(rs) Get number of columns.
|
|
sqlFieldName const char *(*)(rs, col) Get column name by index.
|
|
sqlFieldText const char *(*)(rs, col) Get column value as text by index.
|
|
sqlFieldByName const char *(*)(rs, name) Get column value as text by name.
|
|
sqlFieldInt int32_t (*)(rs, col) Get column value as integer.
|
|
sqlFieldDbl double (*)(rs, col) Get column value as double.
|
|
sqlFreeResult void (*)(rs) Free a result set.
|
|
sqlAffectedRows int32_t (*)(db) Get number of rows affected by last statement.
|
|
.endtable
|
|
|
|
.h2 External Library Callbacks
|
|
|
|
For DECLARE LIBRARY support. The VM resolves external functions at runtime via the host.
|
|
|
|
.code
|
|
void basVmSetExternCallbacks(BasVmT *vm,
|
|
const BasExternCallbacksT *ext);
|
|
.endcode
|
|
|
|
.h3 BasExternCallbacksT
|
|
|
|
.table
|
|
Field Signature Description
|
|
----- --------- -----------
|
|
resolveExtern void *(*)(ctx, libName, funcName) Resolve a native function by library and symbol name. Cached after first call.
|
|
callExtern BasValueT (*)(ctx, funcPtr, funcName, args, argc, retType) Call a resolved native function, marshalling arguments and return value.
|
|
ctx void * User pointer passed to both callbacks.
|
|
.endtable
|
|
|
|
.h2 Form Context
|
|
|
|
Set the active form context during event dispatch.
|
|
|
|
.code
|
|
void basVmSetCurrentForm(BasVmT *vm, void *formRef);
|
|
void basVmSetCurrentFormVars(BasVmT *vm,
|
|
BasValueT *vars, int32_t count);
|
|
.endcode
|
|
|
|
.h2 Stack Access
|
|
|
|
Push and pop values on the evaluation stack for host integration.
|
|
|
|
.code
|
|
bool basVmPush(BasVmT *vm, BasValueT val);
|
|
bool basVmPop(BasVmT *vm, BasValueT *val);
|
|
.endcode
|
|
|
|
Both return true on success, false on stack overflow/underflow.
|
|
|
|
.h2 Error Reporting
|
|
|
|
.code
|
|
const char *basVmGetError(const BasVmT *vm);
|
|
.endcode
|
|
|
|
Returns the current error message string. Valid after basVmRun returns BAS_VM_ERROR.
|
|
|
|
.h2 Sub/Function Calls from Host
|
|
|
|
Call a SUB or FUNCTION by its code address from host code.
|
|
|
|
.code
|
|
bool basVmCallSub(BasVmT *vm, int32_t codeAddr);
|
|
bool basVmCallSubWithArgs(BasVmT *vm, int32_t codeAddr,
|
|
const BasValueT *args, int32_t argCount);
|
|
bool basVmCallSubWithArgsOut(BasVmT *vm, int32_t codeAddr,
|
|
const BasValueT *args, int32_t argCount,
|
|
BasValueT *outArgs, int32_t outCount);
|
|
.endcode
|
|
|
|
.table
|
|
Function Description
|
|
-------- -----------
|
|
basVmCallSub Call a SUB with no arguments.
|
|
basVmCallSubWithArgs Call a SUB with arguments pushed onto the stack frame.
|
|
basVmCallSubWithArgsOut Call a SUB and read back modified argument values after it returns.
|
|
.endtable
|
|
|
|
All three push a call frame, execute until the SUB returns, then restore the previous execution state. Return true on normal completion, false on error or if the VM is not idle.
|
|
|
|
.h2 Debugger API
|
|
|
|
.code
|
|
void basVmSetBreakpoints(BasVmT *vm,
|
|
int32_t *lines, int32_t count);
|
|
void basVmStepInto(BasVmT *vm);
|
|
void basVmStepOver(BasVmT *vm);
|
|
void basVmStepOut(BasVmT *vm);
|
|
void basVmRunToCursor(BasVmT *vm, int32_t line);
|
|
int32_t basVmGetCurrentLine(const BasVmT *vm);
|
|
.endcode
|
|
|
|
.table
|
|
Function Description
|
|
-------- -----------
|
|
basVmSetBreakpoints Set the breakpoint list (sorted array of source line numbers, host-owned memory).
|
|
basVmStepInto Break at the next OP_LINE instruction.
|
|
basVmStepOver Break when call depth returns to the current level.
|
|
basVmStepOut Break when call depth drops below the current level.
|
|
basVmRunToCursor Break when execution reaches the specified source line.
|
|
basVmGetCurrentLine Get the current source line number (from the last OP_LINE instruction).
|
|
.endtable
|
|
|
|
The breakpoint callback notifies the host when a breakpoint fires during nested sub calls:
|
|
|
|
.code
|
|
typedef void (*BasBreakpointFnT)(void *ctx, int32_t line);
|
|
.endcode
|
|
|
|
.h2 BasModuleT
|
|
|
|
Compiled module produced by the BASIC compiler and loaded into the VM.
|
|
|
|
.code
|
|
typedef struct {
|
|
uint8_t *code;
|
|
int32_t codeLen;
|
|
BasStringT **constants;
|
|
int32_t constCount;
|
|
int32_t globalCount;
|
|
int32_t entryPoint;
|
|
BasValueT *dataPool;
|
|
int32_t dataCount;
|
|
BasProcEntryT *procs;
|
|
int32_t procCount;
|
|
BasFormVarInfoT *formVarInfo;
|
|
int32_t formVarInfoCount;
|
|
BasDebugVarT *debugVars;
|
|
int32_t debugVarCount;
|
|
BasDebugUdtDefT *debugUdtDefs;
|
|
int32_t debugUdtDefCount;
|
|
} BasModuleT;
|
|
.endcode
|
|
|
|
.table
|
|
Field Description
|
|
----- -----------
|
|
code P-code bytecode array.
|
|
codeLen Length of bytecode in bytes.
|
|
constants String constant pool.
|
|
constCount Number of string constants.
|
|
globalCount Number of global variable slots needed.
|
|
entryPoint PC of the first instruction (module-level code).
|
|
dataPool DATA statement value pool (for READ).
|
|
dataCount Number of values in the data pool.
|
|
procs Procedure table (SUBs and FUNCTIONs).
|
|
procCount Number of procedures.
|
|
formVarInfo Per-form variable counts and init code addresses.
|
|
formVarInfoCount Number of forms with form-scoped variables.
|
|
debugVars Variable names and metadata for the debugger.
|
|
debugVarCount Number of debug variable entries.
|
|
debugUdtDefs UDT type definitions for the debugger.
|
|
debugUdtDefCount Number of debug UDT definitions.
|
|
.endtable
|