gb_func::gb__build_program - Build and Tokenize Program using .gbf Data
Syntax
call "gb_func::gb__get_file","my.gbf",gb__gbf_data$,"",gb__err$"
call "gb_func::gb__build_program",gb__gbf_data$,"pro5cpl","bbx","", gb__err,gb__err$
Description
This routine is used to build and tokenize a program using data in the .gbf file.
This section describes the program format, tokenization, error handling, and compilation errors for the function used to build and tokenize the program using .gbf data.
Program Format
The program is generated in the following 12 steps:
-
The header block identifies the program, the resource file used to create the program, and copyright information. An ENTER line is generated to allow a single string variable to be optionally passed to the program.
For each of the following, code is generated only if the corresponding variable exists in the [Program] section of the .gbf file:
-
Generate copyright line based on the "Copyright" variable.
-
Generate memory check based on the "Pages" variable.
-
Generate prefix statement based on the "Prefix" variable.
-
Generate precision statement based on the "Precision" variable.
-
Generate gb__show_forms assignment based on the "Show Forms" variable:
-
Show Forms = 0 or None: Initially hide all forms.
-
Show Forms = 1 or First: Initially hide all forms except the first one.
-
Show Forms = 2 or All: Initially show all forms.
rem ' Program Name: C:/basis/vpro5/gb/sample.src
rem ' Resource File: sample.brc
rem ' Generated by GUIBuilder (June 15, 1998 @ 13:08:39)
rem ' Portions Copyright (C) 1997-1998 BASIS International Ltd.
seterr gb__no_arg
enter gb__arg$; gb__args=-1,gb__args=pos($0a$=fattr(gb__arg$,$$),1,0)
gb__no_arg:
seterr 0 -
-
Merge gb_ini.cod (standard initialization block). This file is merged into the generated program immediately after the header block. It contains initialization code and a series of data management functions. The initialization code confirms that the program is running under an interpreter that will support its GUI features, then it sets GB__SYSGUI$ to the first SYSGUI device found in the config.bbx file and GB__SYSPRINT$ to the first SYSPRINT device (if any) found in the config.bbx file. GB__SYSGUI$ is opened on channel GB__SYSGUI; if no SYSGUI device is found, the program terminates. After this basic initialization, the resource file is opened, and all forms from it are displayed (some might be hidden, based on the setting of the gb__show_forms parameter from the .gbf file).
-
Merge in the user-defined initialization code, from the [Init] section in the .gbf file. This will typically do things like DIM record structures, open files, and set global variables. If the program uses grid and/or tab controls, some setup is typically required and would also go in this section. If the program will be using the printer, you can open it here; the printer device is GB__SYSPRINT$ (which will be set to "" if no printer alias was found in config.bbx).
-
Generate event loop based on [Event] blocks. The following is a sample of the generated event loop code.
rem ' -------------------------------------------------------------
rem ' Event Loop
rem ' -------------------------------------------------------------
gb__windows=3; rem ' includes child windowsThis tells us how many windows there are in total.
Note gb__forms tells us the number of top-level windows.
dim gb__closed[gb__windows]
This simply tells us that all windows/forms are initially open.
gb__eoj=0
repeat
readrecord(gb__sysgui,siz=gb__event,err=gb__event_loop_end)gb__event$The following code will retrieve the Notice string into gb__notice$, formatted with the appropriate template. The gb__notice$ variable is only meaningful when gb__event.code$="N":
if gb__event.code$="N" then
: gb__generic$=notice(gb__sysgui,gb__event.x%);
: dim gb__notice$:noticetpl(gb__generic.objtype%,gb__event.flags%);
: gb__notice$=gb__generic$The following block of code returns the window ID given the Event Context. The reverse function is also available -- to return the Context Number for a given window ID, use: gb__context=fngb__context("10.10")
rem ' Get Window ID from Event Context
gb__win_id$=fngb__win_id$(gb__event.context)
if gb__win_id$=$$ then
breakThere will be one of these "while" blocks for each form or child window in the resource file. This is where we decide which event subroutine needs to be called. Note for "X" events, we also track the fact that the window has been closed; when all windows have been closed, the event loop terminates.
rem ' Handle events for window ID 10
while gb__win_id$="10"
if gb__event.id=1 and gb__event.code$="B" then
: gosub W10_C1_PUSH_BUTTON;
: break
if gb__event.id=1000 and gb__event.code$="f" and gb__event.flags=0 then
gosub W10__C1000_LOST_FOCUS;
break
if gb__event.code$="X" then
: gosub W10_WIN_CLOSE;
: gb__closed[1]=1;
: break
break; rem ' catch unhandled events
wend; rem ' End of window ID 10When all windows are closed, the control variable 'gb__eoj' will evaluate to 1, causing the event loop to terminate. Note the developer has the option to force this condition (terminating the event loop) by setting gb__eoj=1 at any time.
if !(gb__eoj) then
: gb__eoj=1;
: for gb__window=1 to gb__windows;
: gb__eoj=(gb__eoj and gb__closed[gb__window]);
: next gb__window
The event loop terminates when gb__eoj is non-zero:
until gb__eoj
gb__event_loop_end: rem --------------------------------------- -
Merge in user-defined code from .gbf [EOJ] block, if any. You would close files and do any other required cleanup here.
-
Merge gb_eoj.cod (standard EOJ/cleanup block). Destroy all contexts (windows) and close gb__sysgui. This is the standard end-of-job routine. It removes all forms from the screen, closes SYSGUI, then stops or exits.
rem gb_eoj.cod - GUIBuilder generated programs: standard EOJ code
rem Copyright (C) 1998 BASIS International Ltd. All Rights Reserved.
rem
rem ***** P R O G R A M E X I T **************************************
rem
gb__eoj:
if gb__forms and gb__sysgui then
: for gb__temp=1 to gb__forms;
: print (gb__sysgui)'context'(gb__form_context[gb__temp]),'destroy'(0);
: next gb__temp
if gb__sysgui then
: close (gb__sysgui)
if tcb(13) then
: exit
: else
: stop -
Merge in gb_err.cod (standard error handler). The error routine displays a message indicating that a particular error occurred at some line number and gives the user the option to retry or end the program. You can insert your own error handler here.
rem gb_err.cod - GUIBuilder generated programs: standard error handler
rem Copyright (C) 1998 BASIS International Ltd. All Rights Reserved.
rem
rem ***** E R R O R H A N D L E R ************************************
rem
gb__err:
gb__temp=msgbox(errmes(err)+" ("+str(err)+")"+
: " occurred at line "+str(tcb(5))+
: " in program "+pgm(-2),5+48,"Error handler")
if gb__temp=4 then
: retry
: else
: goto gb__eoj -
Merge in gb_esc.cod (standard escape handler). If the user presses the break key (Ctrl-C or Break), this routine displays a message indicating that an escape has been detected. The user is given the option to end the program or return to where the escape was detected to continue running the program.
rem gb_esc.cod - GUIBuilder generated programs: standard escape handler
rem Copyright (C) 1998 BASIS International Ltd. All Rights Reserved.
rem
rem ***** E S C A P E H A N D L E R ***********************************
rem
gb__esc:
gb__temp=msgbox("An ESCAPE has been detected. Do you want to end "+
: "this program?",4+32+256,"ESCAPE handler")
if gb__temp=7 then
: return
: else
: goto gb__eoj -
User-defined functions/subroutines defined in the .gbf file are merged into the generated program at this point. Each one will start with a simple comment block giving the subroutine/function name.
-
The event-handler routines from the .gbf file are merged into the generated program at this point. Each one will start with a comment block giving the details of the window, control, and event for which this event handler was defined. The subroutine label and final RETURN statement are also generated; the body of the event handler code is merged in between the subroutine label and the RETURN statement.
-
If there are any standard functions or subroutines that you typically include in all or most of your programs (for example, date formatting or editing), you should put them in this file. The contents of gb_std.cod are merged in to the end of all programs generated by GUIBuilder.
-
Generate the "END" statement.
Tokenization
The generated program is tokenized with the tokenizer specified in the argument list (in this example, "pro5cpl"). The .gbf variable 'Remarks = [y|n]' is used to determine whether comments will appear in the tokenized file. Use 'Remarks = No' to cause remarks to be skipped. The default is 'Remarks = Yes'. The extension of the generated program will also be determined from the argument list; in this case, it's "bbx."
Error Handling
The following lists the errors listed in gb__err:
gb__err |
Error Description |
0 |
Success-no errors. |
-1 |
COMMAND.COM Error: Tokenizer was unable to find workfile. |
-2 |
COMMAND.COM Error: Tokenizer could not be found. |
1..255 |
Unexpected error -- Visual PRO/5 ERR. |
1000 |
Compilation errors reported in gb__err$. |
1001 |
Program Name variable missing from .gbf file. |
1002 |
Resource File variable missing from .gbf file. |
1003 |
Unable to create work file. |
1004 |
Unable to open resource file. |
1010 |
Error detected within _qres::Enumerate_Res_Forms. |
1011 |
Error detected within _qres::Enumerate_Res_Child_Windows. |
1012 |
Error detected within _qres::Enumerate_Res_Controls. |
pro5cpl Compilation Errors
If gb__err=1000, gb__err$ will list the compilation error(s) in the following format:
"type:c(1*=0),line:n(3*=0),msg:c(16*=0),arg1:c(8*=0),arg2:c(8*=0),arg3:c(8*=0)"
Each error will be reported in a string of this format, terminated by a linefeed. There will be one record for each error. The number of errors will be equal to: pos($0a$=gb__err$,1,0).
If type="f", the error was in an include file:
-
line = error line number within the include file, or 0 to indicate an error opening the file.
-
msg = text of error reported by the tokenizer or gb_func::gb__get_file.
-
arg1 = include file which caused the problem:
-
arg2 = ""
-
arg3 = ""
To retrieve the block of code (include file) with the error:
call "gb_func::gb__get_file",arg1$,gb__string$,gb__gbf_data$,gb__err$
If type="g", the error was in user-defined code in the gb__gbf_data$:
-
line = error line number within the .gbf code chunk.
-
msg = text of error reported by gb__bbxcpl$.
-
arg1 = First argument to be passed to fngb__get_code.
-
arg2 = Second argument to be passed to fngb__get_code.
-
arg3 = Third argument to be passed to fngb__get_code.
To retrieve the block of code with the error:
n = fngb__get_code(arg1,arg2,arg3,gb__gbf_data$)
gb__sub_name$ is returned as the name of the event-handler subroutine.
gb__sub_code$ is returned as the body of the event-handler subroutine.
If type="i", the error was in internal (generated) code:
-
line = error line number within the generated program source file.
-
msg = text of error reported by the tokenizer.
-
arg1 = ""
-
arg2 = ""
-
arg3 = ""